把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【CF932E】Team Work(第二类斯特林数简单题)

点此看题面

  • \(\sum_{i=1}^nC_n^i\times i^k\)
  • \(n\le10^9,k\le5\times10^3\)

我这种数学渣渣都能推出来的题目。

而且数据范围很友好,并不需要任何多项式优化。

自然数幂的转化

算是一个经典套路了。

考虑第二类斯特林数的性质:

\[i^k=\sum_{j=0}^{\min\{n,k\}}S_2(k,j)\times i^{\underline{j}} \]

把它代入原式:

\[\sum_{i=1}^{n}C_n^i\times \sum_{j=0}^{\min\{n,k\}}S_2(k,j)\times i^{\underline{j}} \]

看看数据范围,\(n\le10^9\)巨大无比,而\(k\le5\times10^3\)就非常好,所以我们提前\(j\)的枚举:

\[\sum_{j=0}^{\min\{n,k\}}S_2(k,j)\times \sum_{i=1}^n C_n^i\times i^{\underline{j}} \]

针对后一个\(\sum\)中的式子,我们暴拆组合数和下降幂得到:

\[\sum_{i=1}^n \frac{n!}{i!(n-i)!}\times \frac{i!}{(i-j)!}=n!\sum_{i=1}^n\frac1{(n-i)!(i-j)!} \]

后面这一项看起来莫名其妙,但实际上可以发现\((n-i)+(i-j)\)的和是定值\(n-j\)

所以我们给它强行添上一个\((n-j)!\),也刚好让式子前面的\(n!\)变成一个可做的下降幂形式:

\[n^{\underline{j}}\sum_{i=1}^nC_{n-j}^{n-i} \]

组合数上面的\(n-i\)就很难看,不妨用\(n-i\)去替换原本的\(i\)得到:

\[n^{\underline{j}}\sum_{i=0}^{n-1}C_{n-j}^i \]

显然\(n-j\le n-1\),且\(i>n-j\)的时候\(C_{n-j}^i=0\)无用,所以原式等同于:

\[n^{\underline{j}}\sum_{i=0}^{n-j}C_{n-j}^i=n^{\underline{j}}\times 2^{n-j} \]

代回原式:

\[\sum_{j=0}^{\min\{n,k\}}S_2(k,j)\times n^{\underline{j}}\times 2^{n-j} \]

于是只要\(O(k^2)\)预处理第二类斯特林数就结束了。

代码:\(O(k^2)\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define K 5000
#define X 1000000007
using namespace std;
int n,k,S2[K+5][K+5],dw[K+5];
I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
int main()
{
	RI i,j,m,t=0;scanf("%d%d",&n,&k),m=min(n,k);
	for(S2[0][0]=i=1;i<=k;++i) for(j=1;j<=i;++j) S2[i][j]=(1LL*S2[i-1][j]*j+S2[i-1][j-1])%X;//预处理第二类斯特林数
	for(dw[0]=i=1;i<=m;++i) dw[i]=1LL*dw[i-1]*(n-i+1)%X;//预处理下降幂
	RI p=QP(2,n-m);for(i=m;i;p=2LL*p%X,--i) t=(1LL*S2[k][i]*dw[i]%X*p+t)%X;//同时维护好2的幂
	return printf("%d\n",t),0;
}
posted @ 2021-03-26 10:44  TheLostWeak  阅读(78)  评论(0编辑  收藏  举报