1. 程式人生 > >[XSY 1538] 連在一起的幻想鄉

[XSY 1538] 連在一起的幻想鄉

mod 分類 lib style fine dig open cnblogs type

題意

  給定 $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 }

[XSY 1538] 連在一起的幻想鄉