傳送門
題目大意:
有一個隨機數生成器會隨機生成的一個整數,第個數被生成的概率是,每次調用這個生成器生成一個數,把生成的數排成一個序列,當對於每個數都出現了不少於次時停止,求序列的期望長度。
做法:
官方題解的做法過於神仙,這裏給出一種爆推生成函數的做法。
定義,表示在第步內結束的概率,是序列的指數型生成函數,即
顯然有
暴力展開可以化爲其中是係數
最後的答案的形式是
我們發現所有與相關的項的指數都小於,所以這個生成函數是收斂的,可以計算它的係數和。
單獨考慮其中的一項
暴力展開,現在的問題就變成了給定,求
令,可以通過差分遞推求得。
至此整個問題就解決了。
每一步的時間複雜度都是的(假定和同階)
代碼:
#include<bits/stdc++.h>
#define LL long long
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
using namespace std;
inline int read(){
int v=0,f=1;
char c=getchar();
while (c<'0' || c>'9'){
if (c=='-') f=-1;
c=getchar();
}
while (c>='0' && c<='9'){
v=v*10+c-'0';
c=getchar();
}
return v*f;
}
const LL mod=998244353;
const int Maxn=405;
int n,a[Maxn],b[Maxn];
LL p[Maxn],pw[Maxn][Maxn];
LL fact[Maxn],ivf[Maxn];
LL qp(LL x,LL p){
LL ret=1;
while (p){
if (p&1) ret=ret*x%mod;
x=x*x%mod;
p>>=1;
}
return ret;
}
LL inv(LL x){
return qp(x,mod-2);
}
LL dp[Maxn][Maxn][Maxn],S[Maxn];
LL _coef[Maxn][Maxn],tmp[Maxn][Maxn],C[Maxn][Maxn];
void Add(LL &x,LL y){
x+=y;
if (x>=mod) x-=mod;
}
void _init(){
fact[0]=1;
for (int i=1;i<Maxn;i++){
fact[i]=fact[i-1]*i%mod;
}
for (int i=0;i<Maxn;i++) ivf[i]=inv(fact[i]);
for (int i=0;i<Maxn;i++){
for (int j=0;j<=i;j++){
C[i][j]=fact[i]*ivf[j]%mod*ivf[i-j]%mod;
}
}
_coef[0][0]=1;
for (int j=1;j<Maxn;j++){
for (int k=0;k<Maxn;k++){
_coef[j][k]=_coef[j-1][k]*j%mod;
if (k) Add(_coef[j][k],_coef[j-1][k-1]%mod);
}
}
}
int main(){
_init();
scanf("%d",&n);
int sa=0;
for (int i=1;i<=n;i++) scanf("%d %d",&a[i],&b[i]),sa+=a[i];
for (int i=1;i<=n;i++) p[i]=1ll*a[i]*inv(sa)%mod;
for (int i=1;i<=n;i++){
pw[i][0]=1;
for (int j=1;j<Maxn;j++){
pw[i][j]=pw[i][j-1]*p[i]%mod;
}
}
dp[0][0][0]=1;
for (int i=1;i<=n;i++){
for (int j=0;j<=400;j++){
for (int k=0;k<=sa;k++){
if (k>=a[i]){
Add(dp[i][j][k],dp[i-1][j][k-a[i]]);
}
for (int l=0;l<b[i];l++){
if(j>=l) Add(dp[i][j][k],(mod-pw[i][l]*ivf[l]%mod)*dp[i-1][j-l][k]%mod);
}
}
}
}
LL ans=0;
for (int k=0;k<sa;k++){
LL v=1ll*k*inv(sa)%mod;
S[0]=inv((1-v+mod)%mod);
LL t=S[0];
for (int i=1;i<Maxn;i++){
S[i]=0;
for (int l=0;l<i;l++){
LL coef=(i-l)&1?(1):(mod-1);
coef=coef*C[i][l]%mod;
if (l)S[i]+=coef*S[l];
else S[i]+=coef*(S[l]-1);
S[i]%=mod;
}
if (S[i]<0) S[i]+=mod;
S[i]=S[i]*t%mod;
}
for (int j=0;j<=400;j++){
if (dp[n][j][k]){
LL c=mod-dp[n][j][k];
if (k==0){
ans+=c*fact[j];ans%=mod;
continue;
}
LL res=0;
for (int k=0;k<Maxn;k++){
if (_coef[j][k]!=0){
res+=_coef[j][k]*S[k];
res%=mod;
}
}
ans+=c*res;
ans%=mod;
}
}
}
printf("%lld\n",ans);
return 0;
}