BZOJ 5093: 图的价值 第二类斯特林数$O(n \log n)$

时间:2019-01-11
本文章向大家介绍BZOJ 5093: 图的价值 第二类斯特林数$O(n \log n)$,主要包括BZOJ 5093: 图的价值 第二类斯特林数$O(n \log n)$使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

简单题意

一个带标号的图的价值定义为每个点度数的k(<=2e5)k(<=2e5)次方的和。
n(<=1e9)n(<=1e9)个点的带标号的简单无向图的价值之和 (mod998244353)\pmod {998244353}

题解

每个点只有标号之别,故只需要求出一个点的价值之和×n\times n即可。
ans=n2C(n1,2)i=0n1C(n1,i)iki=0n1C(n1,i)ik=i=0n1C(n1,i)j=0kstr2(k,j)j!C(i,j)=j=0kstr2(k,j)j!i=jn1C(n1,i)C(i,j)=j=0kstr2(k,j)j!C(n1,j)i=0n1jC(n1j,i)=j=0kstr2(k,j)j!C(n1,j)2n1j \begin{aligned} &ans =n * 2^{C(n-1,2)}*\sum_{i=0}^{n-1} C(n-1,i) * i^k\\ &\sum_{i=0}^{n-1} C(n-1,i) * i^k = \sum_{i=0}^{n-1} C(n-1,i) * \sum_{j=0}^{k} str2(k,j) * j! * C(i,j)\\ &=\sum_{j=0}^{k}str2(k,j) * j! * \sum_{i=j}^{n-1}C(n-1,i) * C(i,j)\\ &=\sum_{j=0}^{k}str2(k,j) * j! * C(n-1,j) * \sum_{i=0}^{n-1-j} C(n-1-j,i)\\ &=\sum_{j=0}^{k}str2(k,j) * j! * C(n-1,j) * 2^{n-1-j} \end{aligned}
计算第二类斯特林数即可。
容斥原理可得:
str2(n,k)=1k!i=0kC(k,i)(ki)n(1)i=i=0k(1)ii!(ki)n(ki)!str2(n,k) = \frac 1{k!}\sum_{i=0}^k C(k,i) * (k-i)^n*(-1)^i = \sum_{i=0}^k\frac {(-1)^i}{i!}*\frac {(k-i)^n}{(k-i)!}
化为EGF就行了。
FFT O(nlogn)FFT \ O(n \log n)

AC Code:

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define maxn 600005
#define mod 998244353
#define LL long long
using namespace std;

int n,k;
const int inv2 = (mod + 1) / 2;
int w[maxn]={1},r[maxn],lg[maxn],wlen,inv[maxn]={1,1},fac[maxn]={1,1},invf[maxn]={1,1};
int Pow(int base,LL k)
{
	int ret = 1;
	for(;k;k>>=1,base=1ll*base*base%mod) 
		if(k&1) 
			ret = 1ll * ret * base % mod;
	return ret;
}
void Init(int n)
{
	for(wlen=1;n>=2*wlen;wlen<<=1);
	for(int i=1,pw=Pow(3,(mod-1)/(2*wlen));i<=2*wlen;i++) w[i] = 1ll * w[i-1] * pw % mod;
	for(int i=2;i<=2*wlen;i++)	
		lg[i] = lg[i>>1] + 1,
		fac[i] = 1ll * fac[i-1] * i % mod,
		inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod,
		invf[i] = 1ll * invf[i-1] * inv[i] %mod;
}
inline void NTT(int *A,int n,int tp)
{
	int lgn = lg[n];
	for(int i=1;i<n;i++) r[i] = (r[i>>1]>>1)|((i&1)<<(lgn-1));
	for(int i=1;i<n;i++) if(i<r[i]) swap(A[i],A[r[i]]);
	for(int L=2;L<=n;L<<=1)
		for(int st=0,l=L>>1,inc=wlen/l;st<n;st+=L)
			for(int k=st,x=0;k<st+l;k++,x+=inc)
			{
				int tmp = 1ll * (tp == 1 ? w[x] : w[2*wlen-x]) * A[k+l] % mod;
				A[k+l] = (A[k] - tmp) % mod , A[k] = (A[k] + tmp) % mod;
			}
	if(