[题解] CF932E Team Work

CF932E Team Work

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

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

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

一句话题意:求

[sumlimits_{i=1}^n inom{n}{i}i^k ]

哇...这东西怎么算啊...

注意到(k)很小,把(i^k)用第二类斯特林数代替一下

[sumlimits_{i=1}^n inom{n}{i}sumlimits_{j=0}^k egin{Bmatrix}k\jend{Bmatrix}inom{i}{j}j! ]

交换求和顺序

[sumlimits_{j=0}^k egin{Bmatrix}k\jend{Bmatrix}j! sumlimits_{i=1}^n inom{n}{i}inom{i}{j} ]

后面俩组合数...咋整?写一下

[inom{n}{i}inom{i}{j} = frac{n!}{i!(n-i)!} imes frac{i!}{j!(i-j)!} ]

后面的(j!)和前面抵消了,(i!)也消没了 Nice!

[sumlimits_{j=0}^k egin{Bmatrix}k\jend{Bmatrix}sumlimits_{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)!} imes frac{n!}{(n-j)!} ]

可以知道(frac{(n-j)!}{(n-i)!(i-j)!} = inom{n-j}{n-i}),再把第二个因子提到外面柿子变成了

[sumlimits_{j=0}^k egin{Bmatrix}k\jend{Bmatrix}frac{n!}{(n-j)!}sumlimits_{i=1}^n inom{n-j}{n-i} ]

注意到(k ge 1)(egin{Bmatrix}k\0end{Bmatrix}=0),就可以直接对第二个(sum)组合数求和,得到

[sumlimits_{j=0}^k egin{Bmatrix}k\jend{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
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/wxq1229/p/12331057.html