洛谷
CF
求\(\sum_{i=1}^nC_{n}^i*i^k\)ios
寒假的时候被带飞,这题被带着写了一遍。事实上并不难,咱们来颓柿子。
首先回忆一下第二类斯特林数关于整数幂的计算公式:
\[m^n=\sum_{i=0}^mC_{m}^i*S(n,i)*i!\]
\(m^n\)理解为把\(n\)个不一样的球放到\(m\)个不一样的盒子中去。那么咱们枚举有几个盒子非空,用第二类斯特林数乘阶乘计算放置的方案数,最后求和就是结果。
那么直接把\(i^k\)展开
\[\sum_{i=1}^nC_n^i\sum_{j=0}^iC_i^j*S(k,j)*j!\]
把组合数直接拆开
\[\sum_{i=1}^n\frac{n!}{i!(n-i)!}\sum_{j=0}^i\frac{i!}{j!(i-j)!}*S(k,j)*j!\]
化简以后的结果就很好看了。
\[\sum_{i=1}^n\frac{n!}{(n-i)!}\sum_{j=0}^i\frac{S(k,j)}{(i-j)!}\]
\(n\)的范围太大,而\(k\)的范围很小,因此考虑把斯特林数提出来放到外层循环
\[\sum_{j=0}^nS(k,j)\sum_{i=j}^n\frac{n!}{(n-i)!}*\frac{1}{(i-j)!}\]
由于第二类斯特林数\(S(k,j)\)若是\(j>k\)那么结果就是\(0\),因此能够不须要考虑。那么式子能够化简\[\sum_{j=0}^{min(n,k)}S(k,j)\sum_{i=j}^n\frac{n!}{(n-i)!}*\frac{1}{(i-j)!}\]
后面的阶乘孤零零的,给他配点东西就好看了。
\[\sum_{j=0}^{k}S(k,j)\sum_{i=0}^n\frac{n!}{(n-j)!}\frac{(n-j)!}{(n-i)!(i-j)!}\]
\[\sum_{j=0}^{k}S(k,j)\frac{n!}{(n-j)!}\sum_{i=0}^nC_{n-j}^{i-j}\]
\[\sum_{j=0}^{k}S(k,j)\frac{n!}{(n-j)!}2^{n-j}\]
由于\(k\)只有\(5000\),因此\(i\)的起始位置最多只有\(5000\)个,那么直接\(O(k)\)考虑计算便可。
斯特林数暴力\(O(k^2)\)预处理,总的复杂度\(O(k^2)\)。spa
#include<iostream> #include<cstdio> using namespace std; #define MOD 1000000007 #define inv2 500000004 #define MAX 5050 int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;} int n,k,S[MAX][MAX],ans; int main() { scanf("%d%d",&n,&k);S[0][0]=1; for(int i=1;i<=k;++i) for(int j=1;j<=k;++j) S[i][j]=(S[i-1][j-1]+1ll*S[i-1][j]*j)%MOD; for(int j=0,pw=fpow(2,n),nw=1;j<=min(n,k);pw=1ll*pw*inv2%MOD,nw=1ll*nw*(n-j)%MOD,++j) ans=(ans+1ll*S[k][j]*nw%MOD*pw%MOD)%MOD; printf("%d\n",ans); return 0; }