[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;
}
posted @ 2020-10-05 19:13  Arextre  阅读(114)  评论(0编辑  收藏  举报