用斯特林数展开 ik i k
考虑 ∑ni=1(ni)A(i,j) ∑ i = 1 n ( n i ) A ( i , j ) 的组合意义
n n 个物品里选 个的排列,剩下的 n−j n − j 可选可不选
那么 ∑ni=1(ni)A(i,j)=A(n,j)×2n−j ∑ i = 1 n ( n i ) A ( i , j ) = A ( n , j ) × 2 n − j
所以答案就是 ∑kj=1S(k,j)×A(n,j)×2n−j ∑ j = 1 k S ( k , j ) × A ( n , j ) × 2 n − j
O(k2) O ( k 2 )
#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;
}