「ZJOI2019」开关 (生成函数)(概率)

传送门

一道毒瘤的生成函数推导题
一开始发现概率 d p dp dp 加一个高斯消元可以过 50 p t s 50pts 50pts,然后一直在想 d p dp dp……

  • 题解:
    我们令成功了但不结束的概率指数生成函数为 F ( x ) F(x) F(x),直接上单位根反演
    F ( x ) = ∏ i = 1 n ∑ j = 0 ∞ 1 + ( − 1 ) s i + j 2 ∗ ( p i s u m ) j ∗ x j j ! F(x)=\prod_{i=1}^n\sum_{j=0}^{\infty}\frac{1+(-1)^{s_i+j}}{2}*(\frac{p_i}{sum})^j*\frac{x^j}{j!} F(x)=i=1nj=021+(1)si+j(sumpi)jj!xj
    = ∏ i = 1 n e p i s u m x + ( − 1 ) s i e − p i s u m x 2 =\prod_{i=1}^n\frac{e^{\frac{p_i}{sum}x}+(-1)^{s_i}e^{-\frac{p_i}{sum}x}}{2} =i=1n2esumpix+(1)siesumpix
    考虑让成功过后停下来,我们构造走 i i i 步回到本身状态的概率指数生成函数 G ( x ) G(x) G(x),那么
    G ( x ) = ∏ i = 1 n e p i s u m x + e − p i s u m x 2 G(x)=\prod_{i=1}^n\frac{e^{\frac{p_i}{sum}x}+e^{-\frac{p_i}{sum}x}}{2} G(x)=i=1n2esumpix+esumpix
    令走 i i i 步成功的概率的普通生成从函数为 h ( x ) h(x) h(x) F ( x ) , G ( x ) F(x),G(x) F(x),G(x)转为普通生成函数为 f ( x ) , g ( x ) f(x),g(x) f(x),g(x)
    那么有
    f ( x ) = h ( x ) ∗ g ( x ) ⇒ h ( x ) = f ( x ) g ( x ) f(x)=h(x)*g(x)\Rightarrow h(x)=\frac{f(x)}{g(x)} f(x)=h(x)g(x)h(x)=g(x)f(x)
    注意到答案求的就是
    h ′ ( 1 ) = − g ′ ( 1 ) f ( 1 ) + f ′ ( 1 ) g ( 1 ) g ( 1 ) 2 h'(1)=\frac{-g'(1)f(1)+f'(1)g(1)}{g(1)^2} h(1)=g(1)2g(1)f(1)+f(1)g(1)
    下面考虑分别求出 f ( x ) , g ( x ) , f ′ ( x ) , g ′ ( x ) f(x),g(x),f'(x),g'(x) f(x),g(x),f(x),g(x)
    F ( x ) = ∑ i = − s u m s u m a i ∗ e i s u m x F(x)=\sum_{i=-sum}^{sum}a_i*e^{\frac{i}{sum}x} F(x)=i=sumsumaiesumix
    f ( x ) = ∑ i = − s u m s u m a i ∗ 1 1 − i s u m x f(x)=\sum_{i=-sum}^{sum}a_i*\frac{1}{1-\frac{i}{sum}x} f(x)=i=sumsumai1sumix1
    考虑这玩意在 1 处不收敛,将 f , g f,g f,g 同乘 ∏ ( 1 − i s u m x ) \prod (1-\frac{i}{sum}x) (1sumix)
    那么
    f ( x ) = ∑ i = − s u m s u m a i ∏ j ≠ i ( 1 − j s u m x ) f(x)=\sum_{i=-sum}^{sum}a_i\prod_{j\neq i} (1-\frac{j}{sum}x) f(x)=i=sumsumaij=i(1sumjx)
    只在 i = s u m i=sum i=sum 处有值
    f ′ ( x ) = ∑ i = − s u m s u m a i ∑ j ≠ i − j s u m ∏ k ≠ i , k ≠ j ( 1 − k s u m x ) f'(x)=\sum_{i=-sum}^{sum}a_i\sum_{j\neq i}-\frac{j}{sum}\prod_{k\neq i,k\neq j} (1-\frac{k}{sum}x) f(x)=i=sumsumaij=isumjk=i,k=j(1sumkx)
    只在 i = s u m i=sum i=sum j = s u m j=sum j=sum 处有值,于是可以 O ( ∑ p i ) O(\sum p_i) O(pi)
    处理系数 a i a_i ai 就是个背包,复杂度 O ( n ∑ p i ) O(n\sum p_i) O(npi)
#include<bits/stdc++.h>
#define cs const
using namespace std;
int read(){
	int cnt = 0, f = 1; char ch = 0;
	while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1; }
	while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
	return cnt * f;
}
cs int N = 105, M = 1e5 + 50;
cs int Mod = 998244353;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int ksm(int a, int b){ int ans=1; for(;b;b>>=1,a=mul(a,a)) if(b&1) ans=mul(ans,a); return ans; }
void Add(int &a, int b){ a = add(a, b); }
void Dec(int &a, int b){ a = dec(a, b); }
void Mul(int &a, int b){ a = mul(a, b); }
int fix(int a){ return a < 0 ? a + Mod : a; }
int n, s[N], p[N], S, iS, f[M], g[M];
int func(int *f){
	int ans = f[S+S];
	for(int i = -S; i < S; i++) Mul(ans, dec(1,mul(fix(i),iS)));
	return ans;
}
int deriv(int *f){
	static int coef[M];
	int sum = 1, ans = 0;
	for(int i = -S; i < S; i++) Mul(sum, dec(1,mul(fix(i),iS)));
	for(int i = -S; i < S; i++) coef[i+S] = mul(sum, ksm(dec(1,mul(fix(i),iS)),Mod-2));
	sum = 0;
	for(int i = -S; i < S; i++) Add(sum, mul(mul(fix(i),iS), coef[i+S]));
	Add(ans, mul(sum, f[S+S]));
	for(int i = -S; i < S; i++) Dec(ans, mul(f[i+S], coef[i+S]));
	return ans;
}
int main(){
	n = read();
	for(int i = 1; i <= n; i++) s[i] = read();
	for(int i = 1; i <= n; i++) p[i] = read(), S += p[i];
	iS = ksm(S, Mod-2);
	f[S] = g[S] = 1;
	for(int i = 1, now = 0; i <= n; i++){
		static int tf[M], tg[M];
		memset(tf, 0, sizeof(tf)); 
		memset(tg, 0, sizeof(tg));
		for(int j = -now; j <= now; j++){
			if(s[i] == 0) Add(tf[j + S - p[i]], f[j + S]);
			else Dec(tf[j + S - p[i]], f[j + S]);
			Add(tf[j + S + p[i]], f[j + S]);
			Add(tg[j + S + p[i]], g[j + S]);
			Add(tg[j + S - p[i]], g[j + S]);
		}
		memcpy(f, tf, sizeof(tf));
		memcpy(g, tg, sizeof(tg)); now += p[i];
	}
	int fg = func(g), res = mul(fg, deriv(f));
	Dec(res, mul(func(f), deriv(g)));
	cout << mul(res, ksm(mul(fg,fg), Mod-2)); return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值