【题解】[AGC 034 F] RNG and XOR【异或卷积 FWT】

题目链接

题意

一次操作在 ([0,2^n)) 中随机选一个数 (a),概率为 (p_a)。对于所有 (iin [0,2^n)),求期望多少次操作后所有选出的数的异或和为 (i)(nleq 18)

题解

暴力高消显然。考虑将其写作异或卷积的形式,注意 (x_0=0)

[{x_0,x_1,x_2,cdots}oplus{p_0,p_1,p_2,cdots}={x_0+2^n-1,x_1-1,x_2-1,cdots} ]

[{x_0,x_1,x_2,cdots}oplus{p_0-1,p_1,p_2,cdots}={2^n-1,-1,-1,cdots} ]

FWT 求逆即可(对应点值相除)。

#include<bits/stdc++.h>
using namespace std;
const int N=19,mod=998244353;
int p[1<<N],n;
int a[1<<N];
int f[1<<N];

int qpow(int x,int y){
    int ans=1;
    while(y){
        if(y&1)ans=ans*1ll*x%mod;
        x=x*1ll*x%mod;
        y>>=1;
    }
    return ans;
}
void fwt(int *a,int m,int tp){
    for(int i=1;i<1<<m;i<<=1){
        for(int j=0;j<1<<m;j+=i<<1){
            for(int k=0;k<i;k++){
                int x=a[j+k],y=a[i+j+k];
                a[j+k]=x+y;a[i+j+k]=x-y;
                a[j+k]>=mod&&(a[j+k]-=mod);
                a[i+j+k]<0&&(a[i+j+k]+=mod);
            }
        }
    }
    if(tp==-1){
        int q=qpow(1<<m,mod-2);
        for(int i=0;i<1<<m;i++)
            a[i]=a[i]*1ll*q%mod;
    }
}

int main(){
    scanf("%d",&n);
    int s=0;
    for(int i=0;i<1<<n;i++)scanf("%d",p+i),s+=p[i];
    s=qpow(s,mod-2);
    for(int i=0;i<1<<n;i++)p[i]=p[i]*1ll*s%mod;
    p[0]--;
    for(int i=0;i<1<<n;i++)a[i]=mod-1;
    a[0]=(1<<n)-1;
    fwt(p,n,1);
    fwt(a,n,1);
    for(int i=0;i<1<<n;i++)f[i]=a[i]*1ll*qpow(p[i],mod-2)%mod;
    fwt(f,n,-1);
    for(int i=0;i<1<<n;i++)printf("%d
",(f[i]+mod-f[0])%mod);
    return 0;
}

知识共享许可协议
若文章内无特别说明,公开文章采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
原文地址:https://www.cnblogs.com/wallbreaker5th/p/14188160.html