AtCoder Beginner Contest 243 F(思维+dp计数)
Posted 吃花椒的妙酱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 243 F(思维+dp计数)相关的知识,希望对你有一定的参考价值。
题意: n种物品,每种无限个,给定抽到每种物品的概率,抽k次,问抽到m种物品的概率是多少,(n,m,k<=50)
Solution:
\\quad
结果是某种物品取了多少个这种形式,我们写成函数
k
!
∑
i
=
1
n
p
i
c
i
c
i
!
,
∑
[
c
i
>
0
]
=
m
,
∑
c
i
=
k
k!\\sum_i=1^n\\fracp_i^c_ic_i!,\\sum[c_i>0]=m,\\sum c_i = k
k!∑i=1nci!pici,∑[ci>0]=m,∑ci=k,
其中
p
i
表示抽到第
i
种物品的概率,
c
i
表示抽到的
i
的数量
其中p_i表示抽到第i种物品的概率,c_i表示抽到的i的数量
其中pi表示抽到第i种物品的概率,ci表示抽到的i的数量。
然后用dp算上面的式子,dp[i][j][k]表示前i种物品抽到j种,共k个物品的概率
枚举当前第i种物品取了l个,有转移方程
d
p
[
i
]
[
j
]
[
k
]
<
−
d
p
[
i
−
1
]
[
j
−
(
l
>
0
)
]
[
t
−
l
]
∗
p
i
l
l
!
dp[i][j][k] <- dp[i-1][j-(l>0)][t-l] * \\fracp_i^ll!
dp[i][j][k]<−dp[i−1][j−(l>0)][t−l]∗l!pil
时间复杂度O(n^4)
int fac[N],ni_f[N];
ll qsm(int a,int b)
ll ans = 1,tmp=a;
while(b)
if( b&1 ) ans = ans * tmp%mod;
tmp = tmp * tmp%mod;
b>>=1;
return ans;
void ini()
int maxn = 100;
fac[0]=1;
_for(i,1,maxn) fac[i] = fac[i-1]*i%mod;
ni_f[maxn] = qsm(fac[maxn],mod-2);
_rep(i,maxn-1,0) ni_f[i] = ni_f[i+1]*(i+1)%mod;
int dp[N][N][N];
int k,m,n;
int a[N];
signed main()
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
ios;
ini();
int S = 0;
cin>>n>>m>>k;
_for(i,1,n) cin>>a[i],S+=a[i];
_for(i,1,n) a[i] = a[i]*qsm(S,mod-2)%mod;
dp[0][0][0]=1;
_for(i,1,n)
_for(j,0,m)
_for(t,0,k)
_for(l,0,t)
if( j - (l>0) >=0)
dp[i][j][t] = (dp[i][j][t] + dp[i-1][j-(l>0)][t-l] * qsm(a[i],l)%mod*ni_f[l]%mod)%mod;
int ans = dp[n][m][k] * fac[k]%mod;
cout<<ans<<endl;
以上是关于AtCoder Beginner Contest 243 F(思维+dp计数)的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解