[生成函数]2021牛客第四场 B Sample Game

本文介绍了一种基于概率的随机数生成算法,通过分析不同数值出现的次数及其概率,利用生成函数推导出期望长度的计算公式,并给出了具体的实现代码。

题目

有一个随机数生成器,每次生成iii的概率为pip_ipi,如果现在生成的数不小于之前生成的所有数,继续随机,反之,记上分数为n2n^2n2,nnn为已经生成的数的个数

思路

设最长答案长度是lenlenlen,
设生成函数,设它的系数是len>ilen>ilen>i的概率P(len>i)P(len>i)P(len>i),得:f(x)=∑i=0∞P(len>i)xif(x)=\sum_{i=0}^{\infin}P(len>i)x^if(x)=i=0P(len>i)xi

对于一种情况,设第iii个不同的数出现过cnticnt_icnti次,那么该种情况的概率为:∏i=1npicnti\prod_{i=1}^{n}p_i^{cnt_i}i=1npicnti

所以我们可以枚举每一个数可能出现的次数,它的生成函数为:
gi(x)=∑j=0∞pijxj=11−pixg_i(x)=\sum_{j=0}^{\infin}p_i^jx^j=\frac{1}{1-p_ix}gi(x)=j=0pijxj=1pix1

把所有可能的次数乘起来,每一个结果都对应不同的情况:
f(x)=∏i=1ngi(x)f(x)=\prod_{i=1}^{n}g_i(x)f(x)=i=1ngi(x)
带入上方公式:f(x)=∏i=1n11−pixf(x)=\prod_{i=1}^{n}\frac{1}{1-p_ix}f(x)=i=1n1pix1

长度等于iii时的概率P(len=i)=P(len>i−1)−P(len>i)P(len=i)=P(len>i-1)-P(len>i)P(len=i)=P(len>i1)P(len>i)
答案E(len=i)=P(len=i)∗i2E(len=i)=P(len=i)*i^2Elen=i=P(len=i)i2
所有答案为:
∑i=1∞(P(len>i−1)−P(len>i))∗i2\sum_{i=1}^{\infin}(P(len>i-1)-P(len>i))*i^2i=1(P(len>i1)P(len>i))i2
=...+P(len>i−1)i2−P(len>i)i2+P(len>i)∗(i+1)2−P(len>i+1)(i+1)2+...=...+P(len>i-1)i^2-P(len>i)i^2+P(len>i)*(i+1)^2-P(len>i+1)(i+1)^2+...=...+P(len>i1)i2P(len>i)i2+P(len>i)(i+1)2P(len>i+1)(i+1)2+...
=∑i=0∞(P(len>i))∗((i+1)2−i2)=\sum_{i=0}^{\infin}(P(len>i))*((i+1)^2-i^2)=i=0(P(len>i))((i+1)2i2)
(看到有地方再说P(len>0)的时候的问题,i=0的时候也满足这个式子)(看到有地方再说P(len>0)的时候的问题,i=0的时候也满足这个式子)Plen>0i=0
=∑i=0∞(P(len>i))∗(2i+1)=\sum_{i=0}^{\infin}(P(len>i))*(2i+1)=i=0(P(len>i))(2i+1)

f(x)=∑i=1∞P(len>i)xif(x)=\sum_{i=1}^{\infin}P(len>i)x^if(x)=i=1P(len>i)xi
f′(x)=i∗∑i=1∞P(len>i)xi−1f'(x)=i*\sum_{i=1}^{\infin}P(len>i)x^{i-1}f(x)=ii=1P(len>i)xi1
f(1)=∑i=1∞P(len>i)f(1)=\sum_{i=1}^{\infin}P(len>i)f(1)=i=1P(len>i)
f′(1)=i∗∑i=1∞P(len>i)f'(1)=i*\sum_{i=1}^{\infin}P(len>i)f(1)=ii=1P(len>i)

∑i=1∞(P(len>i−1)−P(len>i))∗i2\sum_{i=1}^{\infin}(P(len>i-1)-P(len>i))*i^2i=1(P(len>i1)P(len>i))i2
=...+P(len>i−1)i2−P(len>i)i2+P(len>i)∗(i+1)2−P(len>i+1)(i+1)2+...=...+P(len>i-1)i^2-P(len>i)i^2+P(len>i)*(i+1)^2-P(len>i+1)(i+1)^2+...=...+P(len>i1)i2P(len>i)i2+P(len>i)(i+1)2P(len>i+1)(i+1)2+...

代入原式子:∑i=1∞(P(len>i))∗(2i+1)=2∗f′(1)+f(1)\sum_{i=1}^{\infin}(P(len>i))*(2i+1)=2*f'(1)+f(1)i=1(P(len>i))(2i+1)=2f(1)+f(1)

f(1)=∏i=1n11−pif(1)=\prod_{i=1}^{n}\frac{1}{1-p_i}f(1)=i=1n1pi1
f′(x)=f(x)∑i=1npi1−pixf'(x)=f(x)\sum_{i=1}^{n}\frac{p_i}{1-p_ix}f(x)=f(x)i=1n1pixpi
f′(1)=f(1)∑i=1npi1−pif'(1)=f(1)\sum_{i=1}^{n}\frac{p_i}{1-p_i}f(1)=f(1)i=1n1pipi

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
int w[1000],p[1000];
const int mod =998244353;
int quick_pow(int a,int b){
	int res=1;
	while(b){
		if(b&1) res=res*a%mod;
		b>>=1;
		a=a*a%mod;
	}
	return res;
}
signed main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n;
    cin>>n;
    int ans=0;
    for(int i=1;i<=n;i++){
    	cin>>w[i];
    	ans+=w[i];
	}
	int inv=quick_pow(ans,mod-2)%mod;
	int pp=0,f1=1;
	for(int i=1;i<=n;i++){
		p[i]=w[i]*inv%mod;
		f1=(f1*quick_pow((1-p[i]+mod),mod-2))%mod;
		
		pp=(pp+p[i]*quick_pow(1-p[i]+mod,mod-2)%mod)%mod;
	}
	

	cout<<(f1+2*f1*pp%mod)%mod<<endl;
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值