CF2075E XOR Matrix 题解 数位dp
\text{Description}
- 求整数数列
(a,b) 对数满足集合\{a_i\oplus b_j\} 不超过2 个元素。(其中\oplus 代表位异或) - 其中
a 长度为n ,值域为[0,A] ;b 长度为m ,值域为[0,B] 。 - 多测,答案对
998244353 取模。 -
\text{Solution}
显然若存在
而最终集合不超过
那么就分作四大类讨论:
a 和 b 都为常数列
显然贡献为
a 非常数列 b 为常数列
剔除掉
a 为常数列 b 非常数列
同理,贡献为
a 和 b 都非常数列
不妨令
由
上式也即
不妨记
我们即要统计元素对
发现可以进行数位dp。
设状态为
对第一个
记
-
不在界内,即转移
f_{i,0,0/1,0/1,0/1} 。因为没达到上界所以可以随便取,直接由
f_{i-1,0,0/1,0/1,0/1} 转移过来即可。 -
在界内,即转移
f_{i,1,0/1,0/1,0/1} 。此时乱取可能会导致情况不合法,考虑
[a^1]=0/1 和[A]=0/1 。此时该位置紧贴上界,故前一位不可任意取,需要在界内,即由
f_{i-1,1,0/1,0/1,0/1} 转移来。此时该位置较小保证了小位随意取都可,即可由
f_{i-1,0,0/1,0/1,0/1} 转移来。已出界,为
0 。 -
记得转移前判断当前位异或和是否为
然后发现,唉,我们现在是
那我们还要再多加一层状态
我们提到了什么,“在转移的时候顺便”,那么我们用记忆化搜索来代替递推做数位dp的写法显然更为简洁。
在搜到最后如果发现所有
最终贡献为
最终四大类加和即可。
\text{Time Complexity}
计算快速幂有
多测导致
虽说这个看起来很小但是实际上常数极大。
我们dp的状态数为
则实际上有约
\text{Space Comlexity}
存储dp状态有
\text{Tips}
个人由于调用了不明内存导致调试时出现诡异现象,希望大家不会出现神秘段错误。
\text{Code}
inline void init(){
for(re x=0;x<=M;++x)
for(re i=0;i<=1;++i)
for(re j=0;j<=1;++j)
for(re k=0;k<=1;++k)
for(re l=0;l<=1;++l) f[x][i][j][k][l]=-1;
}
int dfs(int x,int a1,int a2,int b1,int b2,int op){
if(x==-1) return op;
if(f[x][a1][a2][b1][b2]!=-1) return f[x][a1][a2][b1][b2];
f[x][a1][a2][b1][b2]=0;
for(re i=0;i<=(a1?((A>>x)&1):1);++i)
for(re j=0;j<=(a2?i:1);++j)
for(re k=0;k<=(b1?((B>>x)&1):1);++k)
for(re l=0;l<=(b2?k:1);++l)
if(i^j^k^l==0) f[x][a1][a2][b1][b2]=(f[x][a1][a2][b1][b2]+dfs(x-1,a1&(i==((A>>x)&1)),a2&(j==i),b1&(k==((B>>x)&1)),b2&(l==k),op|(i^j)))%mod;
return f[x][a1][a2][b1][b2];
}
// ---------- dp ---------- //
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
// ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
rd(t);
while(t--){
rd(n);rd(m);rd(A);rd(B);int tmp=max(A,B);M=0;
while(tmp>>=1) ++M;init();
ans=1ll*(A+1)*(B+1)%mod;
ans=(ans+1ll*(pw(2,n)-2+mod)%mod*(A+1)%mod*A%mod*inv2%mod*(B+1)%mod)%mod;
ans=(ans+1ll*(pw(2,m)-2+mod)%mod*(B+1)%mod*B%mod*inv2%mod*(A+1)%mod)%mod;
ans=(ans+1ll*dfs(M,1,1,1,1,0)*(pw(2,n)-2+mod)%mod*(pw(2,m)-2+mod)%mod)%mod;
wr(ans);puts("");
}
return 0;
}
// ---------- Main ---------- //