[CF932E]Team Work


https://www.zybuluo.com/ysner/note/1287143

題面

\(\sum_{i=1}^nC(n,i)*i^k\)

  • \(n\leq10^9,k\leq5000\)

解析

很顯然能看出式子的現實意義:從\(n\)個箱子中選出\(i\)個,然后再在這\(i\)個箱子中任意放入\(k\)個球。
這樣箱子有區別,球也有區別。

注意到\(k\)\(n\)小了一個級別。考慮從球的角度下手。
\(k\)個球最多只能放入\(k\)個箱子,除此以外就是很多空箱。
因此,我們可以枚舉球總共放入多少個箱子(不允許空箱),然后其它箱子是選與不選皆可。
設當前放入\(i\)個箱子,則方案數為(\(P\)表示排列數)

\[S(k,i)*P(n,i)*2^{n-i} \]

綜上,最后答案為

\[\sum_{i=1}^kS(k,i)*\frac{n!}{(n-i)!}*2^{n-i} \]

復雜度\(O(k^2)\)
注意\(n<k\)的情況。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define re register
#define il inline
#define db double
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int mod=1e9+7,N=5005;
int n,k,S[5005][5005];
ll ans;
il int gi()
{
  re int x=0,t=1;
  re char ch=getchar();
  while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  if(ch=='-') t=-1,ch=getchar();
  while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  return x*t;
}
il void Pre()
{
  S[0][0]=1;
  fp(i,1,k)
      fp(j,1,i) S[i][j]=(S[i-1][j-1]+1ll*j*S[i-1][j]%mod)%mod;
}
il ll ksm(re ll S,re ll n)
{
  re ll T=S;S=1;
  while(n)
    {
      if(n&1) S=S*T%mod;
      T=T*T%mod;
      n>>=1;
    }
  return S;
}
il ll jc(re int l,re int r)
{
  re ll res=1;
  fp(i,l,r) (res*=i)%=mod;
  return res;
}
int main()
{
  n=gi();k=gi();
  Pre();
  fp(i,1,min(k,n))
      (ans+=1ll*S[k][i]*jc(n-i+1,n)%mod*ksm(2,n-i)%mod)%=mod;
  printf("%lld\n",ans);
  return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM