正题
题目链接:https://www.luogu.com.cn/problem/AT4996
题目大意
给出一个0∼2n−10\sim 2^n-10∼2n−1下标的数组ppp,pip_ipi表示有pip_ipi的权重概率选择iii。
开始有一个x=0x=0x=0,每次选择一个数字yyy让x=xxoryx=x\ xor\ yx=x xor y
对于每个iii求期望多久后第一次变成iii。
1≤n≤181\leq n\leq 181≤n≤18
解题思路
搞一个异或卷积的生成函数,先搞出概率的函数PPP。
然后设EEE表示答案的函数,那么有
E×P+I=E+cE\times P+I=E+cE×P+I=E+c
ccc表示余项,I(x)=∑i=1∞xiI(x)=\sum_{i=1}^{\infty}x^iI(x)=∑i=1∞xi
先求出余项ccc来,设S(A)S(A)S(A)表示生成函数AAA的所有系数和
S(E)×S(P)+S(I)=S(E)+cS(E)\times S(P)+S(I)=S(E)+cS(E)×S(P)+S(I)=S(E)+c
S(P)=1S(P)=1S(P)=1,S(I)=2nS(I)=2^nS(I)=2n,那我们有c=S(I)=2nc=S(I)=2^nc=S(I)=2n
所以就有
E×P+I=E+2nE\times P+I=E+2^nE×P+I=E+2n
E×(P−1)=2n−IE\times (P-1)=2^n-IE×(P−1)=2n−I
FWT(E)=FWT(2n−I)FWT(P−1)FWT(E)=\frac{FWT(2^n-I)}{FWT(P-1)}FWT(E)=FWT(P−1)FWT(2n−I)
然后跑FWTFWTFWT就好了。
注意跑出来的E0≠0E_0\neq 0E0=0,我们要把所有的答案减去E0E_0E0
时间复杂度O(2nn)O(2^nn)O(2nn)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1<<19,P=998244353;
ll n,k,f[N],g[N];
ll power(ll x,ll b){ll ans=1;while(b){if(b&1)ans=ans*x%P;x=x*x%P;b>>=1;}return ans;
}
void FWT(ll *f,ll op){for(ll p=2;p<=n;p<<=1){ll len=(p>>1);for(ll k=0;k<n;k+=p)for(ll i=k;i<k+len;i++){ll x=f[i],y=f[i+len];f[i]=(x+y)*op%P;f[i+len]=(x-y+P)*op%P;}}return;
}
signed main()
{scanf("%lld",&k);n=1<<k;ll sum=0;for(ll i=0;i<n;i++){scanf("%lld",&f[i]);sum=(sum+f[i])%P;g[i]=P-1;}sum=power(sum,P-2);for(ll i=0;i<n;i++)f[i]=f[i]*sum%P;g[0]=(g[0]+n)%P;f[0]=(f[0]+P-1)%P;FWT(f,1);FWT(g,1);for(ll i=0;i<n;i++)f[i]=g[i]*power(f[i],P-2)%P;FWT(f,(P+1)/2);for(ll i=0;i<n;i++)printf("%lld\n",(f[i]-f[0]+P)%P);return 0;
}