Description
每年的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 维矩形,求矩形内部红灯数目,包括边界。
Input
第一行一个正整数t 表示数据组数,对于每组数据:
第一行一个整数k 。
第二行 2k个整数L1,L2..Lk,R1,R2...Rk 描述一个矩形的两个顶点。
T<=10,1<=k<=9,1<=Li<=Ri<=10^15
Output
对于每组数据输出一个整数表示红灯的数目,答案对998244353取模。
打表可知当且仅当 对于每个二进制位,至多有一维坐标为1 时为红色,于是可以从高位到低位进行数位dp,记录每一维坐标已确定部分与Li,Ri的关系($x=L_i || x=R_i || L_i<x<R_i$)
时间复杂度$O(T3^klog(max{R_i}))$
#include<cstdio>
#include<cstring>
typedef long long i64;
const int P=;
int T,n,t;
i64 l[],r[];
int pw3[],ls[],rs[],eq[],peq[];
int f[][],*f1,*f0;
void inc(int&a,int b){b+=a-P;a=b+(b>>&P);}
void dfs(int w,int d,int S,int S2){
if(w==-)return inc(f0[S2],f1[S]);
S*=,S2*=;
if(!peq[w]){
if(!ls[w])dfs(w-,d,S,S2);
dfs(w-,d,S+,S2++rs[w]);
dfs(w-,d,S+,S2+);
if(!d){
dfs(w-,,S,S2+(ls[w]^)*);
if(rs[w])dfs(w-,,S+,S2+);
dfs(w-,,S+,S2+);
}
}else if(!eq[w]){
dfs(w-,d,S,S2);
if(!d)dfs(w-,,S,S2+);
}else if(d+rs[w]<=)dfs(w-,d+rs[w],S,S2);
}
int main(){
for(int i=pw3[]=;i<;++i)pw3[i]=pw3[i-]*;
f[][]=;
for(scanf("%d",&T);T;--T){
scanf("%d",&n);
for(int i=;i<n;++i)scanf("%lld",l+i),--l[i];
for(int i=;i<n;++i)scanf("%lld",r+i),--r[i];
for(t=;t>=;--t){
f1=f[t+];
memset(f0=f[t],,sizeof(int)*pw3[n]);
for(int i=;i<n;++i){
ls[i]=l[i]>>t&;
eq[i]=!((l[i]^r[i])>>t);
peq[i]=!((l[i]^r[i])>>t+);
rs[i]=r[i]>>t&;
}
dfs(n-,,,);
}
int ans=;
for(int i=;i<pw3[n];++i)inc(ans,f0[i]);
printf("%d\n",ans);
}
return ;
}