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

点此看题面

  • (sum_{i=1}^nC_n^i imes i^k)
  • (nle10^9,kle5 imes10^3)

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

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

自然数幂的转化

算是一个经典套路了。

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

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

把它代入原式:

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

看看数据范围,(nle10^9)巨大无比,而(kle5 imes10^3)就非常好,所以我们提前(j)的枚举:

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

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

[sum_{i=1}^n frac{n!}{i!(n-i)!} imes frac{i!}{(i-j)!}=n!sum_{i=1}^nfrac1{(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-jle 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}} imes 2^{n-j} ]

代回原式:

[sum_{j=0}^{min{n,k}}S_2(k,j) imes n^{underline{j}} imes 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
",t),0;
}
败得义无反顾,弱得一无是处
原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF932E.html