AGC034F RNG and XOR
阿新 • • 發佈:2020-07-13
正解
思考的時候沒有得到除了高斯消元以外的思路……
原來是一道板子題……
設\(p_i\)為選\(i\)的概率,\(e_i\)為\(i\)第一次變成\(0\)的期望步數(顯然和\(0\)第一次變成\(i\)一樣)
顯然可以列出式子:
\(e_i=1+\sum p_je_{i\bigoplus j}\)
\(e_0=0\)
用集合冪級數來表示\(e\)和\(p\),分別記為\(E\)和\(P\)。
乘法定義為異或運算。
於是有\(E+c=I+P*E\)
\(I\)表示全部位置都是\(1\)的集合冪級數。
\(c\)是用來修正\(E_0\)的常數。
“集合冪級數”只是個高大上的名詞……
類似於多項式,一個集合冪級數表示成這個樣子:\(F=\sum a_ix^i\)
和多項式不同的是,這裡按照需要定義了\(x^a*x^b\)的結果。比如,如果乘法定義為異或,那麼\(x^a*x^b=x^{a \bigoplus b}\)
設\(S(F)\)表示\(\sum F_i\)
於是有\(S(E)+c=2^n+S(P)S(E)\)
\(S(P*E)=S(P)S(E)\)
因為\(P\)中每個數和\(E\)中每個數都可以做出貢獻。
由於\(S(P)=1\),所以\(c=2^n\)
所以\(E+2^n=I+P*E\)
移項得\(2^n-I=(P-1)*E\)
做\(FWT\)得\(FWT(2^n-I)=FWT(P-1)FWT(E)\)
考慮計算\(FWT(E)_i\)
\(i>0\)時就暴力算出,\(i=0\)時根據\(E_0=0\)手玩出\(FWT(E)_0\)的取值。
算出\(FWT(E)\)之後\(IFWT\)回去即可。
程式碼
using namespace std; #include <cstdio> #include <cstring> #include <algorithm> #define N 18 #define ll long long #define mo 998244353 ll qpow(ll x,int y=mo-2){ ll r=1; for (;y;y>>=1,x=x*x%mo) if (y&1) r=r*x%mo; return r; } int n; int a[1<<N],p[1<<N],e[1<<N],f[1<<N]; void fwt(int F[]){ for (int i=1;i<1<<n;i<<=1) for (int j=0;j<1<<n;j+=i<<1) for (int k=j;k<j+i;++k){ int x=F[k],y=F[k+i]; F[k]=(x+y)%mo; F[k+i]=(x-y+mo)%mo; } } int main(){ scanf("%d",&n); ll sum=0; for (int i=0;i<1<<n;++i) scanf("%d",&a[i]),sum+=a[i]; sum=qpow(sum); for (int i=0;i<1<<n;++i) p[i]=a[i]*sum%mo; for (int i=0;i<1<<n;++i) f[i]=-1+mo; (f[0]+=1<<n)%=mo; fwt(f); (p[0]=p[0]-1+mo)%=mo; fwt(p); sum=0; for (int i=1;i<1<<n;++i){ e[i]=(ll)f[i]*qpow(p[i])%mo; sum+=e[i]; } e[0]=(mo-sum%mo)%mo; fwt(e); ll inv=qpow(1<<n); for (int i=0;i<1<<n;++i) e[i]=e[i]*inv%mo; for (int i=0;i<1<<n;++i) printf("%d\n",e[i]); return 0; }