一道不错的题。
首先我们将整个坐标系数变为以(1…1)为中心
考虑如何判断一个点的颜色
不妨设该点为
其中,xi非0
设
则它的颜色为
奇为红,否则为绿
运用Lucas定理,我们知道该式子为奇的充要条件:
在二进制的意义下没有进位
于是我们得到了这道题的转化问题:
如果我们先容斥,我们可以得到每一维的上界,记为:
我们需要求有多少种
满足
没有进位,且
可以运用数位dp在
的时间内完成
总的时间复杂度为:
这都过了…
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int Mod=998244353;
int K;
ll l[20],r[20];
int f[70][600];
ll num[20];
bool c[20];
inline int calc(){
memset(f,0,sizeof(f));
for(int i=0;i<K;++i)
if(num[i]<0)return 0;
f[60][(1<<K)-1]=1;
for(register int i=60;i>=1;--i)
for(register int j=0;j<(1<<K);++j)
if(f[i][j]){
for(register int k=0;k<K;++k)
if((1<<k)&j)c[k]=((1ll<<(i-1))&num[k]);
else c[k]=true;
//无1
int flag=j;
for(register int k=0;k<K;++k)
if(((1<<k)&j)&&c[k])flag^=(1<<k);
f[i-1][flag]=(f[i-1][flag]+f[i][j])%Mod;
//有1
for(register int k=0;k<K;++k)
if(c[k]){
int now=flag;
if((1<<k)&j)now|=(1<<k);
f[i-1][now]=(f[i-1][now]+f[i][j])%Mod;
}
}
int Ans=0;
for(register int i=0;i<(1<<K);++i)Ans=(Ans+f[0][i])%Mod;
return Ans;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&K);
for(register int i=0;i<K;++i){
scanf("%lld",&l[i]);
l[i]--;
}
for(register int i=0;i<K;++i){
scanf("%lld",&r[i]);
r[i]--;
}
int ans=0;
for(register int i=0;i<(1<<K);++i){
int cnt=0;
for(register int j=0;j<K;++j)
if(i&(1<<j))num[j]=l[j]-1,cnt++;
else num[j]=r[j];
int tmp=calc();
if(cnt&1)ans=(ans-tmp+Mod)%Mod;
else ans=(ans+tmp)%Mod;
}
printf("%d\n",ans);
}
return 0;
}