题面:bzoj5093
题意:定义一个带标号的图的价值为每个点度数的 k k k次方的和 mod 998244353 998244353 998244353。求 n n n个点带标号的简单无向图的价值和。 n ≤ 1 0 9 n \le 10^9 n≤109, k ≤ 200000 k \le 200000 k≤200000
题解:枚举每个点连多少条边: ∑ i = 0 n − 1 ( i n − 1 ) ⋅ i k ⋅ 2 n ( n − 1 ) 2 − ( n − 1 ) \sum _{i=0} ^{n - 1} {i \choose n - 1} \cdot i^k \cdot 2 ^ {\frac {n(n-1)} 2 - (n-1)} ∑i=0n−1(n−1i)⋅ik⋅22n(n−1)−(n−1)
即求 ∑ i = 0 n − 1 ( i n − 1 ) i k \sum _{i=0} ^{n-1} {i \choose n - 1} i^k ∑i=0n−1(n−1i)ik
m n = ∑ i = 0 m S ( n , i ) ( i m ) i ! m^n = \sum _{i=0} ^m S (n, i) {i \choose m} i! mn=∑i=0mS(n,i)(mi)i!,其中 S ( n , i ) S(n, i) S(n,i)为第二类斯特林数
枚举 i i i个盒子非空,方案数为 S ( n , i ) S(n, i) S(n,i), ( i m ) i \choose m (mi)为选出 i i i个盒子的方案数。因为每个盒子不同,再乘 i ! i! i!
代入得: ∑ i = 0 n − 1 ( i n − 1 ) ⋅ ∑ j = 0 i S ( k , j ) ⋅ ( j i ) ⋅ j ! \sum _{i=0} ^{n - 1} {i \choose n - 1} \cdot \sum _{j=0} ^i S(k, j) \cdot {j \choose i} \cdot j! ∑i=0n−1(n−1i)⋅∑j=0iS(k,j)⋅(ij)⋅j!
j j j提到前面: ∑ j = 0 n − 1 S ( k , j ) ⋅ j ! ∑ i = j n − 1 ( i n − 1 ) ( j i ) \sum _{j = 0} ^{n - 1} S (k, j) \cdot j! \sum _{i=j} ^{n - 1} {i \choose n - 1} {j \choose i} ∑j=0n−1S(k,j)⋅j!∑i=jn−1(n−1i)(ij)
考虑后半个式子的组合意义:从 n − 1 n-1 n−1个球中挑 i i i个染黑色,再从 i i i个黑球挑 j j j个染白色。
因为枚举 i i i,所以可以取出任意个染成黑色。等价于从 n − 1 n-1 n−1个球挑 j j j个染白色,剩下 n − 1 − j n-1-j n−1−j个球随意
∑ j = 0 n − 1 S ( k , j ) ⋅ j ! ∑ i = j n − 1 ( i n − 1 ) ( j i ) = ∑ j = 0 n − 1 S ( k , j ) ⋅ j ! ⋅ ( j n − 1 ) 2 n − 1 − j = ∑ j = 0 n − 1 S ( k , j ) ⋅ j ! ⋅ ( n − 1 ) ! j ! ( n − 1 − j ) ! ⋅ 2 n − 1 − j = ∑ j = 0 n − 1 S ( k , j ) ⋅ ( n − 1 ) ! ( n − 1 − j ) ! ⋅ 2 n − 1 − j \begin {aligned} \sum _{j = 0} ^{n - 1} S(k, j) \cdot j! \sum _{i=j} ^{n-1} {i \choose n - 1} {j \choose i} &= \sum _{j = 0} ^{n - 1} S(k, j) \cdot j! \cdot {j \choose n - 1} 2^{n - 1 - j} \\ &= \sum _{j=0} ^{n - 1} S(k, j) \cdot j! \cdot \frac {(n-1)!} {j!(n - 1 - j)!} \cdot 2^{n - 1 - j} \\ &= \sum _{j=0} ^{n-1} S(k, j) \cdot \frac {(n-1)!} {(n-1-j)!} \cdot 2^{n - 1 - j} \end {aligned} j=0∑n−1S(k,j)⋅j!i=j∑n−1(n−1i)(ij)=j=0∑n−1S(k,j)⋅j!⋅(n−1j)2n−1−j=j=0∑n−1S(k,j)⋅j!⋅j!(n−1−j)!(n−1)!⋅2n−1−j=j=0∑n−1S(k,j)⋅(n−1−j)!(n−1)!⋅2n−1−j
第二类斯特林数直接NTT预处理。
当 j > k j \gt k j>k时, S ( k , j ) = 0 S(k, j) = 0 S(k,j)=0。因此算到 k k k即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll ;
const int maxn = 1e6 + 10, mod = 998244353, g = 3 ;
int n, k, ginv ;
ll a[maxn], b[maxn], fac[maxn], inv[maxn] ;
ll power (ll x, int y) {
ll res = 1 ;
while (y) {
if (y & 1) res = res * x % mod ;
x = x * x % mod; y >>= 1 ;
}
return res ;
}
void ntt (ll a[], int n, int f) {
for (int i = 0, j = 0; i < n; i ++) {
if (i > j) swap (a[i], a[j]) ;
for (int t = n >> 1; (j ^= t) < t; t >>= 1) ;
}
for (int i = 2; i <= n; i <<= 1) {
ll wn = power (f ? ginv : g, (mod - 1) / i) ;
for (int j = 0; j < n; j += i) {
ll w = 1 ;
for (int k = 0; k < (i >> 1); k ++, w = w * wn % mod) {
ll A = a[j + k], B = w * a[j + k + (i >> 1)] % mod ;
a[j + k] = (A + B) % mod; a[j + k + (i >> 1)] = (A - B + mod) % mod ;
}
}
}
}
int main() {
scanf("%d%d", &n, &k) ;
fac[0] = inv[0] = 1 ;
for (int i = 1; i <= k; i ++) fac[i] = fac[i - 1] * i % mod ;
inv[k] = power (fac[k], mod - 2) ;
for (int i = k - 1; i >= 1; i --) inv[i] = inv[i + 1] * (i + 1) % mod ;
for (int i = 0; i <= k; i ++) a[i] = 1ll * (i & 1 ? -1 : 1) * inv[i] ;
for (int i = 0; i <= k; i ++) b[i] = power (i, k) * inv[i] % mod ;
int M = 2 * k, N ;
for (N = 1; N <= M; N <<= 1) ;
ginv = power (g, mod - 2) ;
ntt (a, N, 0); ntt (b, N, 0) ;
for (int i = 0; i < N; i ++) a[i] = a[i] * b[i] % mod ;
ntt (a, N, 1) ;
ll invn = power (N, mod - 2), inv2 = power (2, mod - 2) ;
for (int i = 0; i < N; i ++) a[i] = a[i] * invn % mod ;
ll ans = 0, pp = 1, p = power (2, n - 1) ;
for (int i = 0; i <= min (n - 1, k); i ++) {
ans = (ans + a[i] * pp % mod * p % mod) % mod ;
pp = pp * (n - 1 - i) % mod ;
p = p * inv2 % mod ;
}
ans = ans * n % mod ;
ans = ans * power (2, 1ll * (n - 1) * (n - 2) / 2 % (mod - 1)) % mod ;
printf("%lld\n", ans) ;
return 0 ;
}