tsc 考试前 A 的题了,结果到现在才写这篇题解……为了 2mol 我已经一周没碰键盘了,现在 2mol 结束算是可以短暂的春天 短暂地卷一会儿 OI 了((
u1s1 写这篇题解的时候我连题都快忘了。。。
首先设 (b_i=dfrac{A_i}{sumlimits_{j=0}^{2^n-1}A_j}),其次碰到这种期望类的题目我们考虑套路地设 (p_i) 表示异或得到 (i) 的概率,那么有 (p_i=sumlimits_{j=0}^{2^n-1}p_jb_{ioplus j}+1),(p_0=0)。这个状态定义是存在后效性的,而高斯消元 (8^n) 又显然会超时,因此考虑从这个转移式本身入手进行优化。注意到这个转移式长得有点像异或卷积,因此考虑用异或卷积的形式将这个式子写出来,即 (p=p imes b+I),其中 (forall i,I_i=1),异常好理解。
不过事实上这个式子是有个 bug 的,(p_0=0),而将 (p_0) 带到右边去就不一定等于 (0) 了,也就是说左边实际上要加上一个常数 (X),即 (p+X=p imes b+I(Xinmathbb{R}))(事实上很多生成函数的题也需要注意常数项的问题,比如说斐波那契数列,这里就不再赘述了)。怎么求这个 (X) 的值呢?这里又是一个套路,将左边每一项都变成它的系数和,相当于多项式里的令 (x=1),那么可以得到 ((sumlimits_{i=0}^{2^n-1}p_i)+X=(sumlimits_{i=0}^{2^n-1}p_i) imes (sumlimits_{i=0}^{2^n-1}b_i)+(sumlimits_{i=0}^{2^n-1}I_i)),而显然 (sumlimits_{i=0}^{2^n-1}b_i=1),故 (X=sumlimits_{i=0}^{2^n-1}I_i=2^n),因此 (p+2^n=p imes b+I),简单移个项可得 (2^n-I=p imes(b-1)),故 (p=dfrac{2^n-I}{b-1}),把上下两个幂级数 FWTxor 一下相除再 FWTxor 回去即可得到 (p)。
还有一个小问题,就是在求逆元的时候有可能会出现分母为 (0) 的情况。事实上,由于 (A_ile 1000),因此从所有 (b_i) 中任意选出一些出来它们的分子分母都 (<998244353),记 (F= ext{FWT}(b-1)),那么必然有 (F_ile 0(i e 0)),而 (F_0=-1+sumlimits_{i=0}^{2^n-1}b_i=0),因此出错的只可能是 (F_0)。不过这个问题很好解决,我们已知 (p_0=0),而显然对于一个幂级数 (F) FWTxor 后得到的幂级数 (G),常数项上加上一个常数 (C) 对于 (F) 的作用效果就是每一项都加上 (C),因此我们只需输出 (p_i-p_0) 即可。
const int MAXP=1<<18;
const int MOD=998244353;
int qpow(int x,int e=MOD-2){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
return ret;
}
int n,a[MAXP+5],b[MAXP+5],c[MAXP+5];
void FWTxor(int *a,int len,int type){
for(int i=2;i<=len;i<<=1)
for(int j=0;j<len;j+=i)
for(int k=0;k<(i>>1);k++){
int X=a[j+k],Y=a[(i>>1)+j+k];
a[j+k]=1ll*(X+Y)*type%MOD;
a[(i>>1)+j+k]=1ll*(X-Y+MOD)*type%MOD;
}
}
int main(){
scanf("%d",&n);n=1<<n;int sum=0;
for(int i=0;i<n;i++) scanf("%d",&a[i]),sum+=a[i];sum=qpow(sum);
for(int i=0;i<n;i++) a[i]=1ll*a[i]*sum%MOD;a[0]=(a[0]-1+MOD)%MOD;
for(int i=0;i<n;i++) b[i]=MOD-1;b[0]=(b[0]+n)%MOD;
FWTxor(a,n,1);FWTxor(b,n,1);
for(int i=0;i<n;i++) c[i]=1ll*b[i]*qpow(a[i])%MOD;
FWTxor(c,n,MOD+1>>1);
for(int i=0;i<n;i++) printf("%d
",(c[i]-c[0]+MOD)%MOD);
return 0;
}