• AGC034F题解


    题意简述

    给定 (n)(2^n) 个数,初始有一个数(x=0),每次操作有一定概率选中 (i) ,并将 (x) 变成 (x mathrm{xor} i) ,问将 (x) 第一次变为某个数的期望操作次数。

    (nle 18)

    算法分析

    (E(i)) 表示 (x) 第一次从 (0) 变为 (i) 的期望步数。

    不难得到如下 (2^n) 个方程:

    [E(0)=0 ]

    [E(i)=1+sum_{j mathrm{xor} k=i}a_jcdot E(k) , i eq 0 ]

    这个形式是比较标准的 FWT 形式,考虑把 (E(i)) 写成生成函数:

    [E=I+E*A ]

    (注:此处的乘号表示的是广义乘法,本题中对应 xor 卷积)

    但这个式子对常数项等细节处理并不正确,当我们把两边的所有系数相加,会发现 (0=2^n)

    因此实际上是这样的:

    [E+2^n=I+E*A ]

    [E=frac{I-2^n}{1-A} ]

    这样在 FWT 后点值可以直接相除,即可解决。

    最后还有一个问题,把上面求出的 (E) 进行 IFWT 后会发现可能不满足 (E(0)=0) ,考虑回到最原始的式子:

    [E(i)=1+sum_{j mathrm{xor} k=i}a_jcdot E(k) , i eq 0 ]

    因为 (sum a_i=0) ,所以对所有 (E(i)) 同时加上一个常数 (t) 不影响正确性,即可调整。

    时间复杂度 (O(n2^n))

    代码实现

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 1000005
    #define maxm 2000005
    #define inf 0x3f3f3f3f
    #define int long long
    #define mod 998244353
    #define local
    void file(string s){freopen((s+".in").c_str(),"r",stdin);freopen((s+".out").c_str(),"w",stdout);}
    template <typename Tp> void read(Tp &x){
    	int fh=1;char c=getchar();x=0;
    	while(c>'9'||c<'0'){if(c=='-'){fh=-1;}c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c&15);c=getchar();}x*=fh;
    }
    int ksm(int b,int p,int Mod=mod){int ret=1;while(p){if(p&1)ret=1ll*ret*b%Mod;b=1ll*b*b%Mod;p>>=1;}return ret;}
    int n,m;
    int a[maxn],b[maxn],e[maxn];
    void fwt(int *f,int typ){
    	for(int len=1;len<n;len<<=1){
    		for(int i=0;i<n;i+=(len<<1)){
    			for(int j=0;j<len;++j){
    				int l=f[i+j],r=f[i+j+len];
    				f[i+j]=(l+r)%mod;
    				f[i+j+len]=(l-r+mod)%mod;
    			}
    		}
    	}
    	if(typ==-1){
    		int NN=ksm(n,mod-2);
    		for(int i=0;i<n;++i)f[i]=1ll*f[i]*NN%mod;
    	}
    }
    signed main(){
    	int sm=0;
    	read(n);n=(1<<n);
    	for(int i=0;i<n;++i)read(a[i]),sm=(sm+a[i])%mod;
    	sm=ksm(sm,mod-2);
    	for(int i=0;i<n;++i)a[i]=1ll*a[i]*sm%mod;
    	a[0]=(a[0]-1+mod)%mod;//处理出 1-A
    	for(int i=0;i<n;++i)b[i]=(mod-1);
    	b[0]=(b[0]+n+mod)%mod;//处理出 I-2^n
    	fwt(a,1);fwt(b,1);
    	for(int i=0;i<n;++i)e[i]=1ll*b[i]*ksm(a[i],mod-2)%mod;//直接点值相除
    	fwt(e,-1);
    	for(int i=0;i<n;++i)printf("%lld
    ",(e[i]-e[0]+mod)%mod);//调整
    	return 0;
    }
    
  • 相关阅读:
    excel打印预览后整个表格中按页显示虚线,打印时就会打印很多页
    4.8 自定义下拉菜单模式Spinner与setDropDownViewResource
    1.2Matlab基本语法和基本操作.
    CTime类的一个BUG
    【转载】PE_Info 之DIY
    ubuntu使用记录
    反VM测试成功
    获取MAC地址
    【转载】秒到oep,支持所有壳,包括vmp
    【转载】Make your owner PE Protector
  • 原文地址:https://www.cnblogs.com/ZigZagKmp/p/14383479.html
Copyright © 2020-2023  润新知