问题描述
You have a team of N people. For a particular task, you can pick any non-empty subset of people. The cost of having x people for the task is (x^{k}) 。
Output the sum of costs over all non-empty subsets of people.
输入格式
Only line of input contains two integers (N (1<=N<=10^{9})) representing total number of people and (k (1<=k<=5000)).
输出格式
Output the sum of costs for all non empty subsets modulo (10^{9}+7) .
样例输入
1 1
样例输出
1
题目大意
求(sum_{i=1}^n C(n,i) imes i^k)
解析
首先,我们要知道这样一个跟斯特林数有关的公式:
[n^k=sum_{i=0}^{n} egin{Bmatrix}i\k end{Bmatrix} imes C_n^i imes i!
]
带入原式,我们有:
[sum_{i=1}^n C(n,i) imes i^k = sum_{i=1}^nC_n^i imes sum_{j=0}^{i}egin{Bmatrix}j\k end{Bmatrix} imes C_i^j imes j!\
]
对于每一个斯特林数,我们把他提出来,计算斯特林数前的系数:
[sum_{i=1}^nC_n^i imes sum_{j=0}^{i}egin{Bmatrix}j\k end{Bmatrix} imes C_i^j imes j!=sum_{j=0}^{k}egin{Bmatrix}j\k end{Bmatrix} imes sum_{i=0}^kC_n^i imes C_i^j imes j!
]
对于后面的系数部分,我们运用组合意义对其进行化简。这个式子相当于计算(k)次选择,第(i)次从(n)个球中选择(i)个球,再从(i)个球中选择(j)个进行排列的方案数。等价于我们可以直接选择(j)个球进行排列,其他的球可以选或者不选。所以,我们有:
[egin{align}
sum_{i=0}^kC_n^i imes C_i^j imes j!&=C_n^j imes j! imes2^{n-j}\
&=frac{n!}{(n-j)!} imes 2^{n-j}
end{align}
]
所以,原式等于
[sum_{j=0}^{k}egin{Bmatrix}j\k end{Bmatrix} imesfrac{n!}{(n-j)!} imes 2^{n-j}
]
斯特林数可以预处理,2的幂次可以用快速幂解决。至于中间的阶乘,因为(j)的变化量只有(k),是可以预处理的。那么这道题就完成了。
代码
#include <iostream>
#include <cstdio>
#define int long long
#define N 5002
using namespace std;
const int mod=1000000007;
int n,k,i,j,S[N][N],C[N];
int read()
{
char c=getchar();
int w=0;
while(c<'0'||c>'9') c=getchar();
while(c<='9'&&c>='0'){
w=w*10+c-'0';
c=getchar();
}
return w;
}
int poww(int a,int b)
{
long long ans=1,base=a;
while(b){
if(b&1) ans=ans*base%mod;
base=base*base%mod;
b>>=1;
}
return ans;
}
signed main()
{
n=read();k=read();
S[0][0]=1;
for(i=1;i<=k;i++){
for(j=1;j<=i;j++) S[i][j]=(1LL*S[i-1][j-1]+S[i-1][j]*j%mod)%mod;
}
C[0]=1;
for(i=1;i<=k;i++) C[i]=1LL*C[i-1]*(n-i+1)%mod;
long long ans=0;
for(i=0;i<=min(n,k);i++) ans=(ans+1LL*S[k][i]*C[i]%mod*poww(2,n-i)%mod)%mod;
printf("%lld
",ans);
return 0;
}