题目
分析
分析完题面后,发现题目要我们求的就是
∑
∑
a
i
=
D
,
0
≤
a
i
D
!
∏
(
a
i
+
k
)
!
\sum_{\sum{a_i}=D,0\le a_i}\frac{D!}{\prod (a_i+k)!}
∑∑ai=D,0≤ai∏(ai+k)!D!
然后发现这个式子和排列组合很像。
原式去掉
k
k
k以后发现
∑
∑
a
i
=
D
,
0
≤
a
i
D
!
∏
a
i
=
n
D
\sum_{\sum{a_i}=D,0\le a_i}\frac{D!}{\prod a_i}=n^D
∑∑ai=D,0≤ai∏aiD!=nD
于是我们可以试图把原式改写成去掉
k
k
k以后的形式:
∑
∑
a
i
=
D
+
n
k
,
k
≤
a
i
D
!
∏
a
i
\sum_{\sum{a_i}=D+nk,k\le a_i}\frac{D!}{\prod a_i}
∑∑ai=D+nk,k≤ai∏aiD!
然后发现这个式子中有
k
≤
a
i
k\le a_i
k≤ai这个限制。我们也没有什么好方法去直接求解。
那么可以思考没有这个限制时,原式会变成:
∑
∑
a
i
=
D
+
n
k
,
0
≤
a
i
D
!
∏
a
i
\sum_{\sum{a_i}=D+nk,0\le a_i}\frac{D!}{\prod a_i}
∑∑ai=D+nk,0≤ai∏aiD!
=
>
=>
=>
D
!
(
D
+
n
k
)
!
∑
∑
a
i
=
D
+
n
k
,
0
≤
a
i
(
D
+
n
k
)
!
∏
a
i
\frac{D!}{(D+nk)!}\sum_{\sum{a_i}=D+nk,0\le a_i}\frac{(D+nk)!}{\prod a_i}
(D+nk)!D!∑∑ai=D+nk,0≤ai∏ai(D+nk)!
=
>
=>
=>
D
!
(
D
+
n
k
)
!
n
D
+
n
k
\frac{D!}{(D+nk)!}n^{D+nk}
(D+nk)!D!nD+nk
但是,现在的
a
i
a_i
ai是有限制的。
于是我们就要把不符合的答案都减去。那怎么减?
可以用容斥原理,
−
有
一
个
a
i
<
k
+
有
两
个
a
i
<
k
−
有
三
个
a
i
<
k
.
.
.
-有一个a_i<k+有两个a_i<k-有三个a_i<k...
−有一个ai<k+有两个ai<k−有三个ai<k...
那具体怎么求,可以开一个
d
p
dp
dp数组,
d
p
i
,
j
dp_{i,j}
dpi,j表示将
j
j
j个球分成
i
i
i组,每组数量
<
k
<k
<k的方案数。
那么可以求得
d
p
i
,
j
=
∑
t
=
0
k
−
1
d
p
i
−
1
,
j
−
t
C
j
t
dp_{i,j}=\sum_{t=0}^{k-1}dp_{i-1,j-t}C_{j}^{t}
dpi,j=∑t=0k−1dpi−1,j−tCjt
把不符合的都减去,就可以求得最终的式子了:
D
!
(
D
−
n
k
)
!
∑
i
=
0
n
(
−
1
)
i
∑
j
=
0
i
(
k
−
1
)
C
n
i
C
D
+
n
k
j
d
p
i
,
j
(
n
−
i
)
D
+
n
k
−
j
\frac{D!}{(D-nk)!}\sum_{i=0}^{n}(-1)^i\sum_{j=0}^{i(k-1)}C_n^iC_{D+nk}^jdp_{i,j}(n-i)^{D+nk-j}
(D−nk)!D!∑i=0n(−1)i∑j=0i(k−1)CniCD+nkjdpi,j(n−i)D+nk−j
然后就是暴力求解了(快速幂还是要的)。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll dp[55][3000],n,m,k,D,ans;
ll C[3000][3000];
const ll mod=998244353;
ll km(ll x,ll y)
{
ll xx=1;
while(y)
{
if (y&1) xx=xx*x%mod;
x=x*x%mod;
y>>=1;
}
return xx;
}
int main()
{
scanf("%lld%lld%lld",&n,&k,&D);
for (ll i=0;i<=2505;i++)
C[i][0]=1;
for (ll i=1;i<=2505;i++)
for (ll j=1;j<=2505;j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
dp[0][0]=1;
for (ll i=0;i<n;i++)
for (ll j=0;j<=i*(k-1);j++)
for (ll t=0;t<k;t++)
dp[i+1][j+t]=(dp[i+1][j+t]+dp[i][j]*C[j+t][t])%mod;
ans=0;
ll id=1;
for (ll i=0;i<=n;i++)
{
ll CC=1;
for (ll j=0;j<=i*(k-1);j++)
{
ans=(ans+(mod+id*C[n][i])%mod*dp[i][j]%mod*km(n-i,D+n*k-j)%mod*CC%mod)%mod;
CC=CC*(D+n*k-j)%mod*km(j+1,mod-2)%mod;
}
id=-id;
}
for (ll i=D+1;i<=D+n*k;i++)
ans=ans*km(i,mod-2)%mod;
printf("%lld\n",ans);
}