0%

[ABC231G] Balls in Boxes

很久以前写过的一道题。

今天突然发现题解全是生成函数,就来补一篇正常一点的。

题目链接

题意

现在有 个盒子,第 个盒子初始有 个小球。

现在要进行 次操作,每一次随机向一个盒子放一个小球。

设最终第 个盒子里有 个小球,求 的期望。

题解

首先设

那么

考虑把这个式子暴力拆开。

那么就是对于每一个 ,选出 中的一个,然后乘起来,最后加和。

为前 个数中选出 ,乘积的和是多少。

那么有转移

这个时候 就表示所有数中选出 ,乘积的和是多少。

这个时候我们只需要求出,剩下 期望乘积是多少。

首先发现,任意 期望乘积都是一样的。

所以我们只需要求出 表示取 ,期望乘积是多少,这里不妨假设是前 个盒子。

表示第 个操作,有没有向第 个盒子投球。

那么 ,考虑继续拆期望。 直接计算每一项,单项是 的。

最终答案就是

时间复杂度

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//BADC ABCD ABCA DBAA
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<map>
#define inf 0x3f3f3f3f3f3f3f3fll
using namespace std;
const int mod=998244353;
using ll=long long;
using pli=pair<ll,int>;
using pi=pair<int,int>;
template<typename A>
using vc=vector<A>;
inline int read()
{
int s=0,w=1;char ch;
while((ch=getchar())>'9'||ch<'0') if(ch=='-') w=-1;
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
ll dp[1001][1001];
int a[1001];
int n,k;
ll ans;
inline ll qow(ll a,int b)
{
ll ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
inline ll E(int n)
{
ll val=1;
for(int i=0;i<n;i++) val=val*(k-i)%mod;
// printf("%lld\n",val*qow(qow(::n,n),mod-2)%mod);
return val*qow(qow(::n,n),mod-2)%mod;
}
int main()
{
n=read(),k=read();
for(int i=1;i<=n;i++) a[i]=read()%mod;
dp[0][0]=1;
for(int i=1;i<=n;i++)
{
dp[i][0]=1;
for(int j=1;j<=i;j++) dp[i][j]=(dp[i-1][j]+dp[i-1][j-1]*a[i])%mod;
}
for(int i=0;i<=n;i++)
{
// printf("%d : %lld ",i,dp[n][i]);
ans=(ans+dp[n][i]*E(n-i))%mod;
}
printf("%lld\n",ans);
return 0;
}

感谢观看!