专栏文章
CF2075E XOR Matrix 题解 数位dp
CF2075E题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipq7erj
- 此快照首次捕获于
- 2025/12/03 16:09 3 个月前
- 此快照最后确认于
- 2025/12/03 16:09 3 个月前
- 求整数数列 对数满足集合 不超过 个元素。(其中 代表位异或)
- 其中 长度为 ,值域为 ; 长度为 ,值域为 。
- 多测,答案对 取模。
- 。
显然若存在 ,则有 。
而最终集合不超过 个元素,则可知整数数列 和 中也各自最多有 个不同的数值。
那么就分作四大类讨论:
和 都为常数列
显然贡献为 。
非常数列 为常数列
剔除掉 为常数列的可能,贡献为 。
为常数列 非常数列
同理,贡献为 。
和 都非常数列
不妨令 ,。
由 可知,,否则集合中将至少有 个元素。
上式也即 。
不妨记 和 为 中两个不同元素,同理记 和 。
我们即要统计元素对 的个数,满足:
-
,。
-
,。
-
。
发现可以进行数位dp。
设状态为 ,表示处理到从小到大第 位, 是否在 上界内的方案数。
对第一个 讨论转移方案,其余三个同理。
记 为当前位 的取值,同理记 为当前位 的取值。
-
不在界内,即转移 。因为没达到上界所以可以随便取,直接由 转移过来即可。
-
在界内,即转移 。此时乱取可能会导致情况不合法,考虑 和 。
-
。此时该位置紧贴上界,故前一位不可任意取,需要在界内,即由 转移来。
-
。此时该位置较小保证了小位随意取都可,即可由 转移来。
-
。已出界,为 。
-
记得转移前判断当前位异或和是否为 ,如此便可转移 。
然后发现,唉,我们现在是 与 ,我们还没剔除掉 和 。
那我们还要再多加一层状态 在转移的时候顺便判断是否存在过 和 的状况。
我们提到了什么,“在转移的时候顺便”,那么我们用记忆化搜索来代替递推做数位dp的写法显然更为简洁。
在搜到最后如果发现所有 或 时则不计入即可。
最终贡献为 。
最终四大类加和即可。
计算快速幂有 ,数位dp有 。
多测导致 。
虽说这个看起来很小但是实际上常数极大。
我们dp的状态数为 ,每次转移有 项。
则实际上有约 的常数。
存储dp状态有 ,但是与时间复杂度一样,有巨大常数,约 。
个人由于调用了不明内存导致调试时出现诡异现象,希望大家不会出现神秘段错误。
CPP
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 ---------- //
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...