CF1710C XOR Triangle
一个常数更小的做法。
对于 \(a \oplus b + b \oplus c = a \oplus c\) ,令 \(A = a \oplus b\) ,\(B = b \oplus c\) ,则 \(a \oplus c = A \oplus B\) 。
显然有 \(A \oplus B \leq A + B\) 。
则需要满足题意,只需扣除存在 \(a \oplus b + b\oplus c = a \oplus c\) 或与其等价式子的三元组即可。
现在我们通过数位 \(dp\) 求解 \(a \oplus b + b\oplus c = a \oplus c\) 的三元组个数。
记 \(f_{i,0/1,0/1,0/1}\) 表示完成了前 \(i\) 个字符, \(n\) 为给定的字符串 ,\(a,b,c\) 是否与 \(n\) 全部相等的个数。
根据上述条件,每一个二进制位都要满足 \(a \oplus b + b \oplus c = a \oplus c\) 。
这样的 \((a,b,c)\) 有 \(6\) 种。
有 \((0,0,0),(0,0,1),(0,1,1),(1,0,0),(1,1,0),(1,1,1)\) 共 \(6\) 种。
根据数位 \(dp\) 的操作转移即可。
具体转移式子可以参考代码。
最后通过容斥将重复算的减去即可。
有两个以上等式的三元组都很容易计算。
#include<cstdio>
const int N=20000020;
const unsigned int mod=998244353;
unsigned long long f[2][2][2][2],now,res,ans;
char s[N];
int main(){
int i,n=0,o=0;
scanf("%s",s),f[0][0][0][0]=1;
for(i=0;s[i];i++,n++)now=now*2%mod,now+=s[i]-'0';
for(i=0;i<n;i++,o^=1){
if(s[i]=='0') {
f[o^1][0][0][0]=f[o][0][0][0];
f[o^1][1][0][0]=f[o][1][0][0]*2%mod;
f[o^1][0][0][1]=f[o][0][0][1]*2%mod;
f[o^1][0][1][1]=f[o][0][1][1]*3%mod;
f[o^1][1][0][1]=f[o][1][0][1]*3%mod;
f[o^1][1][1][0]=f[o][1][1][0]*3%mod;
f[o^1][1][1][1]=f[o][1][1][1]*6%mod;
}
else {
f[o^1][0][0][0]=f[o][0][0][0];
f[o^1][1][0][0]=(f[o][1][0][0]*2+f[o][0][0][0])%mod;
f[o^1][0][0][1]=(f[o][0][0][1]*2+f[o][0][0][0])%mod;
f[o^1][0][1][1]=(f[o][0][1][1]*3+f[o][0][0][1]+f[o][0][1][0]*2+f[o][0][0][0])%mod;
f[o^1][1][0][1]=(f[o][1][0][1]*3+f[o][0][0][1]+f[o][1][0][0])%mod;
f[o^1][1][1][0]=(f[o][1][1][0]*3+f[o][1][0][0]+f[o][0][1][0]*2+f[o][0][0][0])%mod;
f[o^1][1][1][1]=(f[o][1][1][1]*6+f[o][0][1][1]*3+f[o][1][0][1]*3+f[o][1][1][0]*3+f[o][0][0][1]*2+f[o][1][0][0]*2+f[o][0][0][0])%mod;
}
}
for(i=0;i<8;i++)res=(res+f[o][i&1][(i>>1)&1][(i>>2)&1])%mod;
now=(now+1)%mod,ans=(1llu*4*mod+now*now%mod*now+3*now%mod*now-now-3*res)%mod;
printf("%lld\n",(ans+mod)%mod);
return 0;
}
把第一维彻底压去。
#include<cstdio>
const int N=20000020;
const unsigned int mod=998244353;
unsigned long long f[2][2][2],now,res,ans;
char s[N];
int main(){
int i,n=0,o=0;
fread(s,1,N,stdin);
for(i=0;s[i]>='0'&&s[i]<='1';i++,n++)now=now*2%mod,now+=s[i]-'0';
for(i=0;i<n;i++,o^=1){
if(s[i]=='0') {
f[1][0][0]=f[1][0][0]*2%mod;
f[0][0][1]=f[0][0][1]*2%mod;
f[0][1][1]=f[0][1][1]*3%mod;
f[1][0][1]=f[1][0][1]*3%mod;
f[1][1][0]=f[1][1][0]*3%mod;
f[1][1][1]=f[1][1][1]*6%mod;
}
else {
f[1][1][1]=(f[1][1][1]*6+f[0][1][1]*3+f[1][0][1]*3+f[1][1][0]*3+f[0][0][1]*2+f[1][0][0]*2+1)%mod;
f[0][1][1]=(f[0][1][1]*3+f[0][0][1]+f[0][1][0]*2+1)%mod;
f[1][0][1]=(f[1][0][1]*3+f[0][0][1]+f[1][0][0])%mod;
f[1][1][0]=(f[1][1][0]*3+f[1][0][0]+f[0][1][0]*2+1)%mod;
f[1][0][0]=(f[1][0][0]*2+1)%mod;
f[0][0][1]=(f[0][0][1]*2+1)%mod;
}
}
for(i=1;i<8;i++)res=(res+f[i&1][(i>>1)&1][(i>>2)&1])%mod;res=res+1;
now=(now+1)%mod,ans=(1llu*4*mod+now*now%mod*now+3*now%mod*now-now-3*res)%mod;
printf("%lld\n",(ans+mod)%mod);
return 0;
}

浙公网安备 33010602011771号