1. 程式人生 > >【CodeForces】932 E. Team Work

【CodeForces】932 E. Team Work

嘗試 spl none 分享圖片 公式 題意 opened 快速 sum

【題目】E. Team Work

【題意】給定n和k,n個人中選擇一個大小為x非空子集的代價是x^k,求所有非空子集的代價和%1e9+7。n<=10^9,k<=5000。

【算法】斯特林反演

【題解】枚舉非空子集大小,則題目要求:

$$ans=\sum_{i=1}^{n}\binom{n}{i}i^k$$

對通常冪進行斯特林反演,得到:

$$ans=\sum_{i=1}^{n}\binom{n}{i}\sum_{j=1}^{k}\begin{Bmatrix} k\\ j \end{Bmatrix}*i^{\underline{j}}$$

第二類斯特林數和i無關,因此提出來,從而嘗試將下降冪和組合數搭配起來:

$$ans=\sum_{j=1}^{k}\begin{Bmatrix} k\\ j \end{Bmatrix}\sum_{i=1}^{n}\frac{n!}{(n-i)!(i-j)!}$$

如果(n-i)!(i-j)!是組合數的分母,那分子就是n-i+i-j=n-j,所以拆分$n!=(n-j)!*n^{\underline{j}}$,得到:

$$ans=\sum_{j=1}^{k}\begin{Bmatrix} k\\ j \end{Bmatrix}*n^{\underline{j}}\sum_{i=1}^{n}\binom{n-j}{n-i}$$

後面可以直接用組合數求和公式,得到:

$$ans=\sum_{j=1}^{k}\begin{Bmatrix} k\\ j \end{Bmatrix}*n^{\underline{j}}*2^{n-j}$$

然後O(k^2)預處理第二類斯特林數,然後O(k log k)得到答案。如果模數是998244353的話,還可以NTT求第二類斯特林數。

另外要註意快速冪的指數是負數時直接退出。

技術分享圖片
#include<cstdio>
int n,m,s[5010][5010],ans,x,M=1e9+7;
int p(int x,int k){if(k<0)return 0;int s=1;while(k){if(k&1)s=1ll*s*x%M;x=1ll*x*x%M;k>>=1;}return s;}
int main(){
    scanf("%d%d",&n,&m);s[1
][1]=x=1; for(int i=2;i<=m;i++)for(int j=1;j<=m;j++)s[i][j]=(s[i-1][j-1]+1ll*s[i-1][j]*j)%M; for(int i=1;i<=m;i++)ans=(ans+1ll*s[m][i]*(x=1ll*x*(n-i+1)%M)%M*p(2,n-i))%M; printf("%d",ans); }
View Code

【CodeForces】932 E. Team Work