CF 932E Team Work
阿新 • • 發佈:2018-11-23
題目大意:求\(\sum\limits_{i=0}^{n}C_{n}^{i}i^{k}\)。
我們根據套路\(n^{k}=\sum\limits_{i=0}^{k}C_{n}^{i}i!S_2(k,i)\)。\(S_2\)表示第二類斯特林數。
\[ 原式=\displaystyle\sum_{i=0}^{n}C_{n}^{i}\sum_{j=0}^{k}C_{i}^{j}\cdot j!S_2(k,j)\\ =\sum_{i=0}^{n}C_n^i\sum_{j=0}^k C_i^jj!S_2(k,j) \]
因為\(k\)的規模遠小於\(n\)的規模,所以我們交換一下求和符號,在最外層列舉到\(k\)
\[ 原式=\displaystyle\sum_{j=0}^{k}S_2(k,j)j!\sum_{i=j}^{n} C_n^iC_i^j。 \]
這裡有一個結論:\(C_n^iC_i^j=C_n^jC_{n-i}^{j-i}。\\它的組合數意義是:先從n個數中取i個,再在那i個數中取j個;與先取j個,再在剩下的數中取i-j個。這兩個方案是等價的。\)
這樣,我們就得到了一個\(O(k)的式子:\displaystyle\sum_{j=0}^{k}S_2(k,j)j!C_n^j\sum_{i=j}^{n} C_{n-j}^{i-j}\)。
計算\(C_n^j\)的時候可以計算\(n!*(n-1)!*...*(n-j+1)!再除以j!\)
然後\(\displaystyle\sum_{i=j}^{n} C_{n-j}^{i-j}=\sum_{d=0}^{n-j}C_{n-j}^d=2^{n-j}\)。於是這個問題就解決了。
程式碼:
#include<bits/stdc++.h> #define ll long long using namespace std; inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} ll n,k; ll fac[5005],inv[5005],suf[5005]; ll s[5005][5005]; const ll mod=1e9+7; ll ksm(ll t,ll x) { ll ans=1; for(;x;x>>=1,t=t*t%mod) if(x&1) ans=ans*t%mod; return ans; } ll C(int n,int m) {return fac[n]*ksm(fac[m]*fac[n-m]%mod,mod-2)%mod;} ll cal(int n,int k) { if(!k) return 1; return suf[k-1]*inv[k]%mod; } int main() { n=Get(),k=Get(); s[0][0]=1; for(int i=1;i<=k;i++) for(int j=1;j<=i;j++) s[i][j]=(s[i-1][j-1]+j*s[i-1][j])%mod; fac[0]=1; for(int i=1;i<=k;i++) fac[i]=fac[i-1]*i%mod; inv[k]=ksm(fac[k],mod-2); for(int i=k-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod; suf[0]=n; for(int i=1;i<=k;i++) suf[i]=suf[i-1]*(n-i)%mod; ll ans=0; int lim=min(n,k); for(int i=0;i<=lim;i++) { (ans+=s[k][i]*fac[i]%mod*cal(n,i)%mod*ksm(2,n-i)%mod)%=mod; } cout<<ans; return 0; }