题意
给定 $n$ , 求所有 $n$ 个点的简单连通图的边数的平方的和.
$n \le 2000$ .
分析
$(x + y) ^ 2 = x ^ 2 + 2xy + y ^ 2$ .
我们合并的时候, 要对所有的 $x$ 和 $y$ 进行求和.
$\sum [(x + y) ^ 2] = \sum (x ^ 2) \sum (y ^ 0) + 2 \sum x \sum y + \sum (x ^ 0) \sum (y ^ 2)$ .
设 $h_0[n]$ 为 $n$ 个点的简单图的个数.
$h_0[n] = 2 ^ {\frac{n(n-1)}{2}}$ .
设 $h_1[n]$ 为 $n$ 个点的简单图的边数的和.
$h_1[n] = \frac{n(n-1)}{2} 2 ^ {\frac{n(n-1)}{2} - 1}$ .
设 $h_2[n]$ 为 $n$ 个点的简单图的边数的平方的和.
我们考虑枚举与 $1$ 号点相连的边的数量.
$h_2[n] = \sum_{i = 0} ^ {n-1} \binom{n-1}{i} (i \times i \times h_0[n-1] + 2 \times i \times h_1[n-1] + h_2[n-1])$ .
设 $f_0[n]$ 为 $n$ 个点的简单连通图的个数.
我们考虑用总的连通图的个数, 减掉不合法的, 不合法的按照与 $1$ 号点所在的连通块个数进行分类.
$f_0[n] = h_0[n] - \sum_{i = 1} ^ {n-1} \binom{n-1}{i-1} f_0[i] \times h_0[n-i]$ .
设 $f_1[n]$ 为 $n$ 个点的简单连通图的边数的和.
$f_1[n] = h_1[n] - \sum_{i = 1} ^ {n-1} \binom{n-1}{i-1} (f_0[i] \times h_1[n-i] + f_1[i] \times h_0[n-i])$ .
设 $f_2[n]$ 为 $n$ 个点的简单连通图的边数的平方的和.
$f_2[n] = h_2[n] - \sum_{i = 1} ^ {n-1} \binom{n-1}{i-1} (f_2[i] \times h_0[n-i] + 2 \times f_1[i] \times h_1[n-i] + f_0[i] \times h_2[n-i])$ .
实现
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 6 inline int rd(void) { 7 int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; 8 int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; 9 } 10 11 const int N = 1005; 12 13 int s, MOD; 14 int c[N][N], h0[N], h1[N], h2[N], f0[N], f1[N], f2[N]; 15 16 inline int pwr(int j) { 17 int mul = 1; for (int i = 2; j > 0; j >>= 1, i = 1LL * i * i % MOD) if (j & 1) mul = 1LL * mul * i % MOD; return mul; 18 } 19 20 int main(void) { 21 #ifndef ONLINE_JUDGE 22 freopen("xsy1538.in", "r", stdin); 23 #endif 24 25 scanf("%d %d", &s, &MOD); 26 27 F(i, 0, s) { 28 c[i][0] = 1; 29 F(j, 1, i) 30 c[i][j] = (c[i-1][j] + c[i-1][j-1]) % MOD; 31 } 32 33 F(n, 0, s) 34 h0[n] = pwr(n * (n-1) / 2); 35 36 F(n, 0, s) 37 h1[n] = 1LL * n * (n-1) / 2 * pwr(n * (n-1) / 2 - 1) % MOD; 38 39 F(n, 0, s) 40 F(i, 0, n-1) { 41 int t = (1LL * i * i * h0[n-1] + 2LL * i * h1[n-1] + h2[n-1]) % MOD; 42 h2[n] = (h2[n] + 1LL * c[n-1][i] * t) % MOD; 43 } 44 45 F(n, 0, s) { 46 f0[n] = h0[n]; 47 F(i, 1, n-1) { 48 int t = 1LL * f0[i] * h0[n-i] % MOD; 49 f0[n] = (f0[n] - 1LL * c[n-1][i-1] * t) % MOD; 50 } 51 } 52 53 F(n, 0, s) { 54 f1[n] = h1[n]; 55 F(i, 1, n-1) { 56 int t = (1LL * f1[i] * h0[n-i] + 1LL * f0[i] * h1[n-i]) % MOD; 57 f1[n] = (f1[n] - 1LL * c[n-1][i-1] * t) % MOD; 58 } 59 } 60 61 F(n, 0, s) { 62 f2[n] = h2[n]; 63 F(i, 1, n-1) { 64 int t = (1LL * f2[i] * h0[n-i] + 2LL * f1[i] * h1[n-i] + 1LL * f0[i] * h2[n-i]) % MOD; 65 f2[n] = (f2[n] - 1LL * c[n-1][i-1] * t) % MOD; 66 } 67 } 68 printf("%d\n", (f2[s] + MOD) % MOD); 69 70 return 0; 71 }