题目大意: 给出 n , k n,k n,k,求 ∑ i = 1 n C n i × i k \sum_{i=1}^n C_n^i \times i^k ∑i=1nCni×ik。
题解
看到 i k i^k ik 就想到用第二类斯特林数来展开了。
考虑这个东西的意义:将 k k k 个不同的小球放到 i i i 个不同的盒子中的方案数。那么可以枚举一个 j j j,表示有 j j j 个盒子不是空的(剩下的 i − j i-j i−j 个是空的),那么方案数为 C i j × S ( k , j ) × j ! C_i^j\times S(k,j)\times j! Cij×S(k,j)×j!, C i j C_i^j Cij 表示从 i i i 个盒子中选出 j j j 个不为空的盒子,然后将 k k k 个不同的小球放进去的方案数就是第二类斯特林数 S ( k , j ) S(k,j) S(k,j),由于盒子是不一样的,所以还要乘上 j ! j! j!。
然后大力推一下柿子:
∑
i
=
1
n
C
n
i
×
i
k
=
∑
i
=
1
n
C
n
i
∑
j
=
1
n
C
i
j
×
S
(
k
,
j
)
×
j
!
=
∑
j
=
1
n
S
(
k
,
j
)
×
j
!
∑
i
=
1
n
C
n
i
C
i
j
=
∑
j
=
1
n
S
(
k
,
j
)
×
j
!
∑
i
=
1
n
C
n
j
C
n
−
j
i
−
j
=
∑
j
=
1
n
S
(
k
,
j
)
×
j
!
×
C
n
j
∑
i
=
j
n
C
n
−
j
i
−
j
=
∑
j
=
1
n
S
(
k
,
j
)
×
j
!
×
n
!
j
!
(
n
−
j
)
!
×
2
n
−
j
=
∑
j
=
1
n
S
(
k
,
j
)
×
n
!
(
n
−
j
)
!
×
2
n
−
j
\begin{aligned} &~~~~~\sum_{i=1}^n C_n^i \times i^k\\ &=\sum_{i=1}^n C_n^i \sum_{j=1}^n C_i^j \times S(k,j)\times j!\\ &=\sum_{j=1}^n S(k,j)\times j! \sum_{i=1}^n C_n^i C_i^j\\ &=\sum_{j=1}^n S(k,j)\times j! \sum_{i=1}^n C_n^jC_{n-j}^{i-j}\\ &=\sum_{j=1}^n S(k,j)\times j! \times C_n^j \sum_{i=j}^n C_{n-j}^{i-j}\\ &=\sum_{j=1}^n S(k,j)\times j! \times \frac {n!} {j!(n-j)!} \times 2^{n-j}\\ &=\sum_{j=1}^n S(k,j) \times \frac {n!} {(n-j)!} \times 2^{n-j}\\ \end{aligned}
i=1∑nCni×ik=i=1∑nCnij=1∑nCij×S(k,j)×j!=j=1∑nS(k,j)×j!i=1∑nCniCij=j=1∑nS(k,j)×j!i=1∑nCnjCn−ji−j=j=1∑nS(k,j)×j!×Cnji=j∑nCn−ji−j=j=1∑nS(k,j)×j!×j!(n−j)!n!×2n−j=j=1∑nS(k,j)×(n−j)!n!×2n−j
此时其实已经可以求解了,虽然枚举的上限是 n n n,但是可以发现,当 j j j 大于 k k k 时 S ( k , j ) = 0 S(k,j)=0 S(k,j)=0,所以不需要枚举到 j > k j>k j>k 的部分,那么先 k 2 k^2 k2 预处理 S ( k , j ) S(k,j) S(k,j),就可以求出答案了。
代码如下:
#include <cstdio>
#define maxn 5010
#define mod 1000000007
int n,k,S[maxn][maxn],ans=0;
int ksm(int x,int y)
{
int re=1;
while(y)
{
if(y&1)re=1ll*re*x%mod;
x=1ll*x*x%mod;y>>=1;
}
return re;
}
int min(int &x,int &y){return x<y?x:y;}
int main()
{
scanf("%d %d",&n,&k);
S[0][0]=1;
for(int i=1;i<=k;i++)for(int j=1;j<=i;j++)
S[i][j]=(1ll*S[i-1][j]*j%mod+S[i-1][j-1])%mod;
for(int i=1,prod=n;i<=min(n,k);prod=1ll*prod*(n-i)%mod,i++)
ans=(ans+1ll*S[k][i]*prod%mod*ksm(2,n-i)%mod)%mod;
printf("%d",ans);
}