ans=∑i=1n(ni)ikans=∑i=1n(ni)ik
用斯特林数展开 ikik
ans=∑i=1n(ni)∑j=1kS(k,j)A(i,j)ans=∑i=1n(ni)∑j=1kS(k,j)A(i,j)
=∑j=1kS(k,j)∑i=1n(ni)A(i,j)=∑j=1kS(k,j)∑i=1n(ni)A(i,j)
考虑 ∑ni=1(ni)A(i,j)∑i=1n(ni)A(i,j) 的组合意义
nn 个物品里选 个的排列,剩下的 n−jn−j 可选可不选
那么 ∑ni=1(ni)A(i,j)=A(n,j)×2n−j∑i=1n(ni)A(i,j)=A(n,j)×2n−j
所以答案就是 ∑kj=1S(k,j)×A(n,j)×2n−j∑j=1kS(k,j)×A(n,j)×2n−j
O(k2)O(k2)
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=5010,P=1e9+7;
int S[N][N];
inline int Pow(int x,int y){
int ret=1;
for(;y;y>>=1,x=1LL*x*x%P) if(y&1) ret=1LL*ret*x%P;
return ret;
}
inline int A(int n,int j){
int ret=1;
for(int i=0;i<j;i++)
ret=1LL*ret*(n-i)%P;
return ret;
}
int main(){
S[0][0]=1;
for(int i=1;i<=5000;i++){
for(int j=1;j<=i;j++)
S[i][j]=(S[i-1][j-1]+1LL*j*S[i-1][j])%P;
}
int ans=0;
int n,k; scanf("%d%d",&n,&k);
for(int j=1;j<=k && j<=n;j++)
ans=(ans+1LL*S[k][j]*A(n,j)%P*Pow(2,n-j))%P;
printf("%d\n",ans);
return 0;
}