bzoj5093: [Lydsy1711月赛]图的价值 第二类斯特林数

xiaoxiao2025-10-14  5

Description “简单无向图”是指无重边、无自环的无向图(不一定连通)。 一个带标号的图的价值定义为每个点度数的k次方的和。 给定n和k,请计算所有n个点的带标号的简单无向图的价值之和。 因为答案很大,请对998244353取模输出。 Input 第一行包含两个正整数n,k(1<=n<=10^9,1<=k<=200000)。

做法: 用第二类斯特林数推公式 题解

关于第二类斯特林数 留坑,有空了好好学一波,但是这些公式要怎么才记得住! 没事,有板子,重点会用!

一个简单的模板我却调了很久,写多项式的能力很差!

#include <bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;++i) #define per(i,a,b) for(int i=a;i>=b;--i) #define repd(i,a,b) for(int i=a;i>=b;--i) #define rvc(i,S) for(int i=0;i<(int)S.size();++i) #define fore(i,x) for(int i = head[x] ; i ; i = e[i].next) #define mp make_pair #define pb push_back #define fi first #define se second #define debug(...) fprintf(stderr,__VA_ARGS__) #define lowbit(x) (x&(-x)) using namespace std; #define maxn 600020 typedef long long ll; typedef vector <ll> Poly; const ll mod = 998244353; const ll G = 3 , gi = 3; ll ginv; ll w[2][maxn]; namespace Polygen { inline ll add(ll x,ll y){ x += y; if ( x >= mod ) x -= mod; return x; } inline ll sub(ll x,ll y){ x -= y; if ( x < 0 ) x += mod; return x; } inline ll power(ll x,ll y){ ll res = 1; while ( y ){ if ( y & 1 ) res = res * x % mod; x = x * x % mod; y >>= 1; } return res; } void init(){ ginv = power(G,mod - 2); for (int i = 1; i < (1 << 19); i <<= 1) { ll wn = power(gi, (mod - 1) / (i << 1)); for (int j = 0; j < i; j++) { w[1][i + j] = (j ? wn * w[1][i + j - 1] % mod : 1); } wn = power(gi, mod - 1 - (mod - 1) / (i << 1)); for (int j = 0; j < i; j++) { w[0][i + j] = (j ? wn * w[0][i + j - 1] % mod : 1); } } } void print(const Poly &p){ cout<<p.size()<<endl; rvc(i,p) cout<<p[i]<<" "; cout<<endl; } inline void NTT(Poly &a,int len,int fl) { //预处理原根快了一倍! fl = max(0 , fl); int i , j , k; for (j = 1 , i = ( len >> 1 ) ; j < len; j++) { if (j > i) swap(a[i] , a[j]); for (k = (len>>1) ; k & i; k >>= 1 ) i ^= k; i ^= k; } for (i = 1; i < len; i <<= 1) { for (j = 0; j < len; j += i << 1) { for (k = 0; k < i; k++) { ll x = a[j + k], y = a[j + k + i] * w[fl][i + k] % mod; a[j + k] = add( x , y ); a[j + k + i] = sub( x , y ); } } } if (fl == 0) { ll inv = power(len , mod-2); for (int i = 0; i < len; i++) a[i] = a[i] * inv % mod; } } } using namespace Polygen; Poly S,f,g; int n,k; ll fac[maxn],inv[maxn],pow2[maxn],fac2[maxn]; void pre(){ fac[0] = inv[0] = pow2[0] = fac2[0] = 1; rep(i,1,k) fac[i] = fac[i - 1] * i % mod , inv[i] = power(fac[i],mod - 2) , pow2[i] = pow2[i - 1] * 2 % mod; // cout<<f.size()<<" "<<g.size()<<endl; rep(i,1,k) fac2[i] = fac2[i - 1] * (n - i) % mod; rep(i,0,k){ if ( i & 1 ) f[i] = (mod - inv[i]); else f[i] = inv[i]; g[i] = power(i,k) * inv[i] % mod; // cout<<f[i]<<" "<<g[i]<<endl; } } inline ll C(int n,int m){ if ( n < m ) return 0; return fac2[m] * inv[m] % mod; } int main(){ // freopen("input.txt","r",stdin); init(); scanf("%d %d",&n,&k); int len = ceil(log2(k * 2)); len = 1 << len; f.resize(len) , g.resize(len) , S.resize(len); pre(); NTT(f,len,1) , NTT(g,len,1); rep(i,0,len - 1) S[i] = f[i] * g[i] % mod; NTT(S,len,-1); S[0] = 0; // rep(i,0,min(k,100)) cout<<S[i]<<" "; // cout<<endl; ll ans = 0; rep(i,0,min(n - 1,k)){ ans = (ans + S[i] * fac[i] % mod * C(n - 1,i) % mod * power(2,n - 1 - i)) % mod; } ans = ans * n % mod * power(2,(ll)(n - 1) * (n - 2) / 2 % (mod - 1)) % mod; cout<<ans<<endl; }
转载请注明原文地址: https://www.6miu.com/read-5037881.html

最新回复(0)