[题解] CF932E Team Work

CF932E Team Work

你现在手里有\(n\)个人,你要选出若干个人来搞事情(不能不选),其中选择\(x\)个人出来的代价是\(x^k\),问所有方案的代价总和。

数据范围:\(1\le n \le 10^9,1\le k \le 5000\)

英语不好qwq...题目应该是这个意思吧

一句话题意:求
\[ \sum\limits_{i=1}^n \binom{n}{i}i^k \]
哇...这东西怎么算啊...

注意到\(k\)很小,把\(i^k\)用第二类斯特林数代替一下
\[ \sum\limits_{i=1}^n \binom{n}{i}\sum\limits_{j=0}^k \begin{Bmatrix}k\\j\end{Bmatrix}\binom{i}{j}j! \]
交换求和顺序
\[ \sum\limits_{j=0}^k \begin{Bmatrix}k\\j\end{Bmatrix}j! \sum\limits_{i=1}^n \binom{n}{i}\binom{i}{j} \]
后面俩组合数...咋整?写一下
\[ \binom{n}{i}\binom{i}{j} = \frac{n!}{i!(n-i)!} \times \frac{i!}{j!(i-j)!} \]
后面的\(j!\)和前面抵消了,\(i!\)也消没了 Nice!
\[ \sum\limits_{j=0}^k \begin{Bmatrix}k\\j\end{Bmatrix}\sum\limits_{i=1}^n \frac{n!}{(n-i)!(i-j)!} \]
注意到分母上和为\(n-j\),我们像把他搞成组合数的形式,分子分母同时乘\((n-j)!\)
\[ \frac{n!}{(n-i)!(i-j)!} = \frac{(n-j)!}{(n-i)!(i-j)!} \times \frac{n!}{(n-j)!} \]
可以知道\(\frac{(n-j)!}{(n-i)!(i-j)!} = \binom{n-j}{n-i}\),再把第二个因子提到外面柿子变成了
\[ \sum\limits_{j=0}^k \begin{Bmatrix}k\\j\end{Bmatrix}\frac{n!}{(n-j)!}\sum\limits_{i=1}^n \binom{n-j}{n-i} \]
注意到\(k \ge 1\)\(\begin{Bmatrix}k\\0\end{Bmatrix}=0\),就可以直接对第二个\(\sum\)组合数求和,得到
\[ \sum\limits_{j=0}^k \begin{Bmatrix}k\\j\end{Bmatrix}n^{\underline{j}}2^{n-j} \]
大力\(O(k^2)\)推第二类斯特林数,预处理下降幂就好了。

#include <bits/stdc++.h>
using namespace std;
const int P=1e9+7,N=5010;
inline int fpow(int x,int y)
{
    int ret=1; for(x%=P;y;y>>=1,x=1ll*x*x%P)
        if(y&1) ret=1ll*ret*x%P;
    return ret;
}
inline int add(int x,int y){return (x+=y)>=P?x-P:x;}
inline int sub(int x,int y){return (x-=y)<0?x+P:x;}
int S[N][N],dwn[N],n,k;
int main()
{
    scanf("%d%d",&n,&k);
    dwn[0]=1; for(int i=1;i<=k;i++) dwn[i]=1ll*dwn[i-1]*(n-i+1)%P;
    S[0][0]=1; for(int i=1;i<=k;i++)
        for(int j=1;j<=i;j++)
            S[i][j]=add(S[i-1][j-1],1ll*j*S[i-1][j]%P);
    int ans=0,pw2=fpow(2,n),i2=fpow(2,P-2);
    for(int j=0;j<=k;j++,pw2=1ll*pw2*i2%P)
        ans=add(ans,1ll*S[k][j]*dwn[j]%P*pw2%P);
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wxq1229/p/12322166.html
今日推荐