• UOJ#469. 【ZJOI2019】开关 生成函数


    原文链接www.cnblogs.com/zhouzhendong/p/UOJ469.html

    前言

    clytql当场秒掉此题可惜不知道为什么fst了。

    题解

    考虑构建指数生成函数。

    对于第 (i) 项,设其概率为 (p_i) (即题目中的 (p_i / sum_i p_i)) 。构建指数生成函数:

    [f_i(x) = sum_{jgeq 0, jmod 2 = s_i} p_i ^ j frac {x^ j } { j !} \ = frac 1 2 (e ^ {p_i x } + (-1)^{s_i} e ^ {-p_i x }) ]

    (F(x) = prod_i f_i(x) ,f(x) = sum_{i} i! [x^i]F(x))(k) 次项系数就是随机按 (k) 次开关到达指定状态的概率。

    我们要求的是第一次到达指定状态的概率,所以我们需要将多项式 (f(x)) 除去"(s_i) 全为 0 时的多项式 (g(x))"。

    我们要算的是期望,所以我们要求的是 (sum_{igeq 0} i cdot [x^i]frac{f(x)}{g(x)}),即将 (x=1) 代入下式

    [frac{ m d} { { m d} x } left ( frac {f(x)}{g(x)} ight ) ]

    的各个系数之和。注意由于我们在求 (f(x))(g(x)) 时,就已经乘了一个阶乘将指数生成函数转化成对应的普通生成函数了。因为我们要除去的方案是从终止状态出发再回到终止状态的方案数(OGF),而不是在到达终止状态之前绕一圈的方案数(如果除以EGF)。

    由于

    [cfrac{ m d} { { m d} x } left ( cfrac {f(x)}{g(x)} ight ) = cfrac{f'(x) g(x) - g'(x) f(x) }{g ^ 2(x)} ]

    于是,我们来对每一个项考虑一下:

    [e ^ {kx} = sum_{igeq 0 } k ^ i frac { x ^ i } { i ! } ]

    [sum_{igeq 0} k ^ i x ^ i= frac{1}{1 - kx} ]

    [cfrac{ m d}{{ m d}x}left (frac{1}{1 - kx} ight ) = frac {k} { (1-kx) ^ 2} ]

    接下来我们把 (x = 1) 代入求解。

    考虑到当 (k = 1) 时我们会得到 NAN,这导致了求解失败。

    但是我们显然可以肯定答案不是 NAN。那么发生了什么?

    之前提到,答案是

    [cfrac{f'(x) g(x) - g'(x) f(x) }{g ^ 2(x)} ]

    我们只需要将分子分母上下同乘 ((1-x) ^ 2)

    注意到 (g^2(x)) 里面有 (cfrac {1}{(1-x) ^ 2}) ,但是 $f'(x) g(x) $ 和 (f(x)g'(x)) 里面都有 (cfrac {1}{(1-x) ^ 3}) ,看起来似乎又是 NAN。注意到 $f'(x) g(x) $ 和 (f(x)g'(x)) 里面的 (cfrac {1}{(1-x) ^ 3}) 项在减法时抵消了,所以没有影响。

    总时间复杂度 (O(n sum{p_ i} ))

    代码

    #include <bits/stdc++.h>
    #define clr(x) memset(x,0,sizeof x)
    #define For(i,a,b) for (int i=(a);i<=(b);i++)
    #define Fod(i,b,a) for (int i=(b);i>=(a);i--)
    #define fi first
    #define se second
    #define pb(x) push_back(x)
    #define mp(x,y) make_pair(x,y)
    #define outval(x) cerr<<#x" = "<<x<<endl
    #define outtag(x) cerr<<"---------------"#x"---------------"<<endl
    #define outarr(a,L,R) cerr<<#a"["<<L<<".."<<R<<"] = ";
    						For(_x,L,R)cerr<<a[_x]<<" ";cerr<<endl;
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector <int> vi;
    LL read(){
    	LL x=0,f=0;
    	char ch=getchar();
    	while (!isdigit(ch))
    		f|=ch=='-',ch=getchar();
    	while (isdigit(ch))
    		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return f?-x:x;
    }
    const int N=105,S=1e5+10,mod=998244353;
    int Pow(int x,int y){
    	int ans=1;
    	for (;y;y>>=1,x=(LL)x*x%mod)
    		if (y&1)
    			ans=(LL)ans*x%mod;
    	return ans;
    }
    void Add(int &x,int y){
    	if ((x+=y)>=mod)
    		x-=mod;
    }
    void Del(int &x,int y){
    	if ((x-=y)<0)
    		x+=mod;
    }
    int Add(int x){
    	return x>=mod?x-mod:x;
    }
    int Del(int x){
    	return x<0?x+mod:x;
    }
    int inv2=(mod+1)>>1;
    int n;
    int s[N],p[N],sum=0,invs;
    int f[S],g[S],val[S],inv[N],O=5e4+5;
    int ans=0;
    void Get(int *a){
    	static int b[S];
    	For(i,-sum,sum){
    		a[i+O]=0;
    		val[i+O]=(LL)Del(i)*invs%mod;
    		inv[i+O]=Pow(Del(1-val[i+O]),mod-2);
    	}
    	a[0+O]=1;
    	For(i,1,n){
    		For(j,-sum,sum)
    			b[j+O]=0;
    		For(j,-sum,sum){
    			if (!a[j+O])
    				continue;
    			Add(b[j+p[i]+O],a[j+O]);
    			if (s[i])
    				Del(b[j-p[i]+O],a[j+O]);
    			else
    				Add(b[j-p[i]+O],a[j+O]);
    		}
    		For(j,-sum,sum)
    			a[j+O]=b[j+O];
    	}
    }
    int calc1(int *a,int *b){
    	// a' * b * (1 - x) ^ 2 
    	int ans=0;
    	For(i,-sum,sum-1)
    		Add(ans,(LL)b[i+O]*inv[i+O]%mod);
    	ans=(LL)ans*a[sum+O]%mod;
    	return ans;
    }
    int calc2(int *a){
    	return (LL)a[sum+O]*a[sum+O]%mod;
    }
    int main(){
    	n=read();
    	For(i,1,n)
    		s[i]=read();
    	For(i,1,n)
    		p[i]=read(),sum+=p[i];
    	invs=Pow(sum,mod-2);
    	Get(f),clr(s),Get(g);
    	Add(ans,calc1(f,g));
    	Del(ans,calc1(g,f));
    	ans=(LL)ans*Pow(calc2(g),mod-2)%mod;
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    微信分享 apicloud方式 中遇到的坎
    css之颜色篇
    css总结
    记一些茅塞顿开的事情
    apicloud
    安装MySQL
    智能家居
    java
    数据库设计好不好,分配很重要。
    WP8.1的shell:SystemTray去哪了?
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/UOJ469.html
Copyright © 2020-2023  润新知