[CF932E]Team Work
题目让你求
\[\sum_{i=1}^n{n\choose i}i^k
\]
这道题地重点其实是在于 \(i^k\) 可以怎么表示,先给出结论:
\[\newcommand{\string}[2]{\genfrac{\{}{\}}{0pt}{}{#1}{#2}}
i^k=\sum_{j=0}^k{i\choose j}\string{k}{j}j!
\]
其中 \(\string{k}{j}\) 是第二类斯特林数.
下面用组合意义解释这个等式:
首先,\(i^k\) 其实就是将 \(k\) 个数任意放在 \(i\) 个盒子中,盒子可以为空.
那么,我们先从 \(i\) 个盒子中选出 \(j\) 个,即 \(i\choose j\),再将 \(k\) 个数放在选出来的 \(j\) 个盒子中(盒子不能为空),这就是第二类斯特林数 \(\string{k}{j}\),但是由于第二类斯特林数的盒子是可以无序的,所以我们还要加上盒子的全排,即 \(j!\),那么,就有上面的等式.
我们将 \(i^k\) 展开之后代入原式,有
\[\newcommand{\string}[2]{\genfrac{\{}{\}}{0pt}{}{#1}{#2}}
\begin{aligned}
\sum_{i=1}^n{n\choose i}i^k
&=\sum_{i=1}^n{n\choose i}\sum_{j=0}^k{i\choose j}\string{k}{j}j! \\
&=\sum_{i=1}^n\sum_{j=0}^k{n\choose i}{i\choose j}\string{k}{j}j! \\
&=\sum_{j=0}^k\string{k}{j}j!\sum_{i=1}^n{n\choose i}{i\choose j} \\
&=\sum_{j=0}^k\string{k}{j}j!\sum_{i=1}^n{n\choose j}{n-j\choose i-j} \\
&=\sum_{j=0}^k\string{k}{j}j!{n\choose j}\sum_{i=1}^n{n-j\choose i-j} \\
&=\sum_{j=0}^k\string{k}{j}j!{n\choose j}2^{n-j}
\end{aligned}
\]
至于 \(n\choose j\),我们可以使用递推公式,即
\[{n\choose i}={n\choose i-1}\times i^{-1}\times (n-i+1)
\]
证明展开即可.
#include<iostream>
using namespace std;
namespace IO{
#define rep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i<=i##_end_;++i)
#define fep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i>=i##_end_;--i)
#define low_rep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i<i##_end_;++i)
#define upp_fep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i>=i##_end_;--i)
#define erep(i,u) for(signed i=tail[u],v=e[i].to;i;i=e[i].nxt,v=e[i].to)
#define writc(a,b) fwrit(a),putchar(b)
#define mp(a,b) make_pair(a,b)
#define fi first
#define se second
typedef long long ll;
// typedef pair<int,int> pii;
typedef unsigned long long ull;
typedef unsigned uint;
#define Endl putchar('\n')
// #define int long long
// #define int unsigned
// #define int unsigned long long
#define cg (c=getchar())
template<class T>inline void readin(T& x){
char c;bool f=0;
while(cg<'0'||'9'<c)f|=(c=='-');
for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
if(f)x=-x;
}
template<class T>inline T readin(T x){
x=0;char c;bool f=0;
while(cg<'0'||'9'<c)f|=(c=='-');
for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
return f?-x:x;
}
template<class T>void fwrit(const T x){//just short,int and long long
if(x<0)return (void)(putchar('-'),fwrit(-x));
if(x>9)fwrit(x/10);
putchar(x%10^48);
}
#undef cg
template<class T>inline T Max(const T x,const T y){return x<y?y:x;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
inline int gcd(const int a,const int b){return b?gcd(b,a%b):a;}
inline void getInv(int inv[],const int lim,const int MOD){
inv[0]=inv[1]=1;for(int i=2;i<=lim;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
}
inline ll mulMod(const ll a,const ll b,const ll mod){//long long multiplie_mod
return ((a*b-(ll)((long double)a/mod*b+1e-8)*mod)%mod+mod)%mod;
}
}
using namespace IO;
const int mod=1e9+7;
const int inv2=500000004;
const int maxk=5000;
inline int inv(int a){
int n=mod-2,ret=1;
for(;n>0;n>>=1,a=1ll*a*a%mod)if(n&1)ret=1ll*ret*a%mod;
return ret;
}
inline int qkpow(int a,int n){
int ret=1;
for(;n>0;n>>=1,a=1ll*a*a%mod)if(n&1)ret=1ll*ret*a%mod;
return ret;
}
int S[maxk+5][maxk+5],n,k;
inline void Get_S(){
S[0][0]=1;
rep(i,1,k)rep(j,1,i)
S[i][j]=(S[i-1][j-1]+1ll*S[i-1][j]*j%mod)%mod;
}
int fac,pow2,ans,C;
signed main(){
cin>>n>>k;
Get_S();
fac=C=1,pow2=qkpow(2,n);
rep(j,1,k){
C=1ll*C*inv(j)%mod*(n-j+1)%mod,fac=1ll*fac*j%mod,pow2=1ll*pow2*inv2%mod;
ans=(ans+1ll*S[k][j]*fac%mod*pow2%mod*C)%mod;
}cout<<ans<<'\n';
return 0;
}