AT4996 [AGC034F] RNG and XOR【异或,期望】

    技术2022-07-14  77

    AT4996 [AGC034F] RNG and XOR

    e i e_i ei 表示从 0 走到 i i i 的期望次数,显然等于 i i i 走到 0 的期望次数。 e i = { 0 , i = 0 1 + ∑ j = 0 2 n − 1 e i ⊕ j ∗ p j , i ≠ 0 e_i=\begin{cases}0,&i=0\\1+\sum_{j=0}^{2^n-1}e_{i\oplus j}*p_j,&i\neq 0\end{cases} ei={0,1+j=02n1eijpj,i=0i=0

    E , P E,P E,P 分别为 e i , p i e_i,p_i ei,pi 的集合幂级数,用异或卷积定义乘法,则有: E ∗ P + I = E + c E*P+I=E+c EP+I=E+c 其中 c c c 为一个常数,用于修正 e 0 e_0 e0

    得到 F W T ( E ) ∗ F W T ( P ) + F W T ( I ) = F W T ( E ) + F W T ( c ) FWT(E)*FWT(P)+FWT(I)=FWT(E)+FWT(c) FWT(E)FWT(P)+FWT(I)=FWT(E)+FWT(c) i i i 处的关系式为: F W T ( E ) i ∗ ( F W T ( P ) i − 1 ) = F W T ( c ) i − F W T ( I ) i FWT(E)_i*(FWT(P)_i-1)=FWT(c)_i-FWT(I)_i FWT(E)i(FWT(P)i1)=FWT(c)iFWT(I)i 其中 F W T ( I ) = 2 n FWT(I)=2^n FWT(I)=2n F W T ( c ) = ∑ i = 0 2 n − 1 c x i FWT(c)=\sum_{i=0}^{2^n-1}cx^i FWT(c)=i=02n1cxi i = 0 i=0 i=0 时, F W T ( P ) 0 = ∑ p i = 1 FWT(P)_0=\sum p_i=1 FWT(P)0=pi=1,所以 c = F W T ( I ) 0 = 2 n c=FWT(I)_0=2^n c=FWT(I)0=2n

    对于 i > 1 i>1 i>1 F W T ( P ) i < S ( P ) = 1 FWT(P)_i<S(P)=1 FWT(P)i<S(P)=1,所以 F W T ( E ) i = 2 n F W T ( P ) i − 1 FWT(E)_i=\frac {2^n}{FWT(P)_i-1} FWT(E)i=FWT(P)i12n

    F W T ( E ) 0 FWT(E)_0 FWT(E)0 利用 e 0 = 0 = 1 2 n ∑ j = 0 2 n − 1 F W T ( E ) j e_0=0=\frac 1{2^n}\sum_{j=0}^{2^n-1}FWT(E)_j e0=0=2n1j=02n1FWT(E)j 求解。

    实际上可以假设 F W T ( E ) 0 = 0 FWT(E)_0=0 FWT(E)0=0 求出一个答案 E ′ E' E,然后实际上 E i = E i ′ + 1 2 n F W T ( E ) 0 E_i=E_i'+\frac 1{2^n}FWT(E)_0 Ei=Ei+2n1FWT(E)0,所以 1 2 n F W T ( E ) 0 = 0 − E 0 ′ \frac 1{2^n}FWT(E)_0=0-E_0' 2n1FWT(E)0=0E0

    求出 F W T ( E ) FWT(E) FWT(E) 后再变换回来就可以了。

    双倍经验:ZJOI2019开关,题解里面最后 F W T ( G ) T = ∑ i ∉ T p i − ∑ i ∈ T p i FWT(G)_T=\sum_{i\notin T}p_i-\sum_{i\in T}p_i FWT(G)T=i/TpiiTpi 是因为概率只在单点处有值。

    Code:

    #include<bits/stdc++.h> #define maxn 300005 using namespace std; const int mod = 998244353; int n,N,p[maxn],E[maxn]; int Pow(int a,int b){int s=1;for(;b;b>>=1,a=1ll*a*a%mod) b&1&&(s=1ll*s*a%mod); return s;} int upd(int x){return x+(x>>31&mod);} void FWT(int *a,int len,int flg){ for(int i=2,l=1,v;i<=len;l=i,i<<=1) for(int j=0;j<len;j+=i) for(int k=j;k<j+l;k++) v=a[k],a[k]=upd(v+a[k+l]-mod),a[k+l]=upd(v-a[k+l]); if(flg^1) for(int i=0,Inv=Pow(len,mod-2);i<len;i++) a[i]=1ll*a[i]*Inv%mod; } int main() { scanf("%d",&n),N=1<<n; int s=0; for(int i=0;i<N;i++) scanf("%d",&p[i]),s=upd(s+p[i]-mod); s=Pow(s,mod-2); for(int i=0;i<N;i++) p[i]=1ll*p[i]*s%mod; FWT(p,N,1); for(int i=1;i<N;i++) E[i]=1ll*N*Pow(upd(p[i]-1),mod-2)%mod; FWT(E,N,-1); int x=mod-E[0]; for(int i=0;i<N;i++) printf("%d\n",upd(E[i]+x-mod)); }
    Processed: 0.018, SQL: 9