1. 程式人生 > >BZOJ 5093: 圖的價值 第二類斯特林數$O(n \log n)$

BZOJ 5093: 圖的價值 第二類斯特林數$O(n \log n)$

簡單題意

一個帶標號的圖的價值定義為每個點度數的 k ( < = 2 e 5 )

k(<=2e5) 次方的和。
n ( < = 1 e 9
) n(<=1e9)
個點的帶標號的簡單無向圖的價值之和 ( m o d
998244353 ) \pmod {998244353}

題解

每個點只有標號之別,故只需要求出一個點的價值之和 × n \times n 即可。
a n s = n 2 C ( n 1 , 2 ) i = 0 n 1 C ( n 1 , i ) i k i = 0 n 1 C ( n 1 , i ) i k = i = 0 n 1 C ( n 1 , i ) j = 0 k s t r 2 ( k , j ) j ! C ( i , j ) = j = 0 k s t r 2 ( k , j ) j ! i = j n 1 C ( n 1 , i ) C ( i , j ) = j = 0 k s t r 2 ( k , j ) j ! C ( n 1 , j ) i = 0 n 1 j C ( n 1 j , i ) = j = 0 k s t r 2 ( k , j ) j ! C ( n 1 , j ) 2 n 1 j \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}
計算第二類斯特林數即可。
容斥原理可得:
s t r 2 ( n , k ) = 1 k ! i = 0 k C ( k , i ) ( k i ) n ( 1 ) i = i = 0 k ( 1 ) i i ! ( k i ) n ( k i ) ! 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就行了。
F F T   O ( n log n ) 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