每年的1月10日是温暖节,在这一天,化身出题人的C_SUNSHINE将会给OIer们送温暖。OIer们只要在门口放上一个
仙人掌,就能在早上的某个时刻听到门外传来一声:“开门,送温暖——”作为一个萌萌哒OIer,Salroey从C_SUN
SHINE那里收到了一个令人感到温暖的问题,她想与你分享分享。有一个K维空间,每个整点上都有一个信号灯,每
个信号灯的位置都可以由K 个整数(x1,x2...xk) 表示,信号灯的颜色定义如下:
1.如果存在i满足xi=0则(x1,x2...xk) 为绿色。
2.如果对于所有i满足xi=1 则 (x1,x2...xk)为红色。
3.对于信号灯(x1,x2...xk) ,定义它的k 个前驱为恰好某一维的坐标比这个信号灯恰好少1
其余坐标都与这个信号灯相等的信号灯,即(x1,x2..xi-1,xi+1...xk) 。如果这些前驱中有偶数个红灯
则这个信号灯为绿色,否则为红色。
现在给定k 和一个k 维矩形,求矩形内部红灯数目,包括边界。
第一行一个正整数t 表示数据组数,对于每组数据:
第一行一个整数k 。
第二行 2k个整数L1,L2..Lk,R1,R2...Rk 描述一个矩形的两个顶点。
T<=10,1<=k<=9,1<=Li<=Ri<=10^15
对于每组数据输出一个整数表示红灯的数目,答案对998244353取模。
打表可知当且仅当 对于每个二进制位,至多有一维坐标为1 时为红色,于是可以从高位到低位进行数位dp,记录每一维坐标已确定部分与Li,Ri的关系($x=L_i || x=R_i || L_i<x<R_i$)
#include<cstdio>
#include<cstring>
typedef long long i64;
const int P=998244353;
int T,n,t;
i64 l[11],r[11];
int pw3[11],ls[11],rs[11],eq[11],peq[11];
int f[55][20007],*f1,*f0;
void inc(int&a,int b){b+=a-P;a=b+(b>>31&P);}
void dfs(int w,int d,int S,int S2){
if(w==-1)return inc(f0[S2],f1[S]);
S*=3,S2*=3;
if(!peq[w]){
if(!ls[w])dfs(w-1,d,S,S2);
dfs(w-1,d,S+1,S2+1+rs[w]);
dfs(w-1,d,S+2,S2+2);
if(!d){
dfs(w-1,1,S,S2+(ls[w]^1)*2);
if(rs[w])dfs(w-1,1,S+1,S2+1);
dfs(w-1,1,S+2,S2+2);
}
}else if(!eq[w]){
dfs(w-1,d,S,S2);
if(!d)dfs(w-1,1,S,S2+1);
}else if(d+rs[w]<=1)dfs(w-1,d+rs[w],S,S2);
}
int main(){
for(int i=pw3[0]=1;i<10;++i)pw3[i]=pw3[i-1]*3;
f[51][0]=1;
for(scanf("%d",&T);T;--T){
scanf("%d",&n);
for(int i=0;i<n;++i)scanf("%lld",l+i),--l[i];
for(int i=0;i<n;++i)scanf("%lld",r+i),--r[i];
for(t=50;t>=0;--t){
f1=f[t+1];
memset(f0=f[t],0,sizeof(int)*pw3[n]);
for(int i=0;i<n;++i){
ls[i]=l[i]>>t&1;
eq[i]=!((l[i]^r[i])>>t);
peq[i]=!((l[i]^r[i])>>t+1);
rs[i]=r[i]>>t&1;
}
dfs(n-1,0,0,0);
}
int ans=0;
for(int i=0;i<pw3[n];++i)inc(ans,f0[i]);
printf("%d\n",ans);
}
return 0;
}