AGC034 F - RNG and XOR

简要题意 : \(0\)\(2^n-1\) 的数每一个数有一个出现概率\(p_i\) (保证\(\sum p_i =1\)) ,数x初始是0,每次异或上出现的数,对每个数求x最先变成这个数的期望次数

首先转化问题,考虑我们求的相当于是每个数变成0的期望次数。

于是设\(x[i]\)表示i的答案

\[ \begin {aligned} x[i] &= \sum x[j]*p_{i\ xor\ j} + 1 \ (i>0) \\ x[0] &= 0 \end {aligned} \]

写成异或卷积

\[ \lbrace x[0],x[1],x[2],... \rbrace XOR \lbrace p[0],p[1],p[2],... \rbrace = \lbrace x[0] + {2^n} -1,x[1]-1,x[2]-1,... \rbrace \]

\[ \lbrace x[0],x[1],x[2],... \rbrace XOR \lbrace p[0]-1,p[1],p[2],... \rbrace = \lbrace {2^n} -1,-1,-1,... \rbrace \]

然后异或卷积下做一次求逆就行了。

注意的是0这个位置是{0,0},这个可以用x[0]=0还原。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
inline int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
inline int sub(int a,int b){a-=b;return a<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
const int inv2=qpow(2,mod-2);
/* math */
int n,s;
inline void FWT(int *t,int n,int type){//xor
    for(int step=1;step<n;step<<=1)
        for(int i=0;i<n;i+=step<<1)
            for(int j=0;j<step;j++){
                int x=t[i+j],y=t[i+j+step];
                t[i+j]=add(x,y),t[i+j+step]=sub(x,y);
                if(type==-1)t[i+j]=mul(t[i+j],inv2),t[i+j+step]=mul(t[i+j+step],inv2);
            }
}
const int N=1<<18;
int p[N],a[N];

int main()
{
    cin >> n;
    for(int i=0;i<1<<n;i++)scanf("%d",&p[i]),s=add(s,p[i]);
    s=qpow(s,mod-2);for(int i=0;i<1<<n;i++)p[i]=mul(p[i],s);
    for(int i=1;i<1<<n;i++)a[i]=mod-1;a[0]=(1<<n)-1;
    p[0]=sub(p[0],1);
    FWT(a,1<<n,1),FWT(p,1<<n,1);
    for(int i=0;i<1<<n;i++)a[i]=mul(a[i],qpow(p[i],mod-2));
    FWT(a,1<<n,-1);
    for(int i=0;i<1<<n;i++){
        printf("%d\n",sub(a[i],a[0]));
    }
}

猜你喜欢

转载自www.cnblogs.com/weiyanpeng/p/11005606.html
xor