【The 2018 ACM-ICPC Asia Qingdao Regional Contest】Sub-cycle Graph

题目描述

[题目链接](http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5826)

给定 $n$ 个点,你需要在里面连上 $m$ 条无向边,不能有重边或自环

对于每种连边方式都对应着一张无向图,求有多少种不同的无向图,使得它可以通过加入若干条边后使得整张图变成一个环

数据范围:$3 \le n \le 10^5, 0 \le m \le {n \choose 2}$

题解

那么就相当于只能连出链,由于每加入一条边,就会少一个点,因此一共有 $k=n-m$ 条链

设 $n$ 个点连成一条链的方案数为 $l_n$,则:

$$
l_n=\begin{cases}
1 & \quad (n=1) \\
\frac{n!}{2} & \quad (n > 1)
\end{cases}
$$

考虑链的指数型生成函数 $L(x)$,即:

$$
L(x)=\sum_{n \ge 1} l_n \frac{x^n}{n!}=x+ \frac{x^2}{2} \sum_{n \ge 0} x^n=\frac{x}{1-x}\left(1-\frac{x}{2}\right)
$$

考虑答案的指数型生成函数 $F_k(x)$,即:

$$
F_k(x)=\sum_{n \ge 1} f_{n,k} \frac{x^n}{n!}=L^{k}(x)=\frac{x^k}{(1-x)^k} \left(1-\frac{x}{2}\right)^k
$$

由于链之间也应该是无顺序的,因此还需要除以 $k!$,答案就是:

$$
\frac{[x^n]L^k(x)}{k!}
$$
由于:
$$
\begin{aligned}
&\left( 1-\frac{x}{2} \right)^k \\
=&\sum_{i=0}^{k} {k \choose i} \left(-\frac{1}{2}\right)^i x^i \\
\end{aligned}
$$

同时 $\frac{1}{(1-x)^k}$ 相当于求了 $k$ 次前缀和,对序列 $p$ 求 $k+1$ 次前缀和后 $p'_n=\sum_{i=0}^{n} {k+i \choose k}p_{n-i}$

代码

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 
 5 const int mod = 1e9 + 7, N = 1e5 + 10;
 6 
 7 ll pw(ll a, ll b) {
 8     ll r = 1;
 9     for( ; b ; b >>= 1, a = a * a % mod) {
10         if(b & 1) {
11             r = r * a % mod;
12         }
13     }
14     return r;
15 }
16 
17 ll getinv(ll n) {
18     return pw(n, mod - 2);
19 }
20 
21 ll fac[N], invfac[N];
22 void init(int n) {
23     fac[0] = invfac[0] = 1;
24     for(int i = 1 ; i <= n ; ++ i) {
25         fac[i] = fac[i - 1] * i % mod;
26     }
27     invfac[n] = pw(fac[n], mod - 2);
28     for(int i = n - 1 ; i ; -- i) {
29         invfac[i] = invfac[i + 1] * (i + 1) % mod;
30     }
31 }
32 ll C(int n, int m) {
33     return n < m || m < 0 ? 0 : fac[n] * invfac[m] % mod * invfac[n - m] % mod;
34 }
35 
36 ll n, m;
37 const int inv2 = (mod + 1) / 2;
38 void runprog() {
39     scanf("%lld%lld", &n, &m);
40     if(n < m) {
41         puts("0");
42     } else if(n == m) {
43         printf("%lld\n", fac[n - 1] * inv2 % mod);
44     } else {
45         ll res = 0;
46         ll k = n - m;
47         ll prod = 1;
48         for(int i = m ; ~ i ; -- i) {
49             res += C(k + i - 1, i) * C(k, m - i) % mod * prod % mod;
50             res %= mod;
51             prod = prod * -inv2 % mod;
52         }
53         res = res * fac[n] % mod * invfac[k] % mod;
54         printf("%lld\n", (res % mod + mod) % mod);
55     }
56 }
57 
58 int main() {
59     init(N - 1);
60     int t; scanf("%d", &t);
61     while(t --) {
62         runprog();
63     }
64 }
【The 2018 ACM-ICPC Asia Qingdao Regional Contest】Sub-cycle Graph

 

posted @ 2019-06-14 15:54  KingSann  阅读(149)  评论(0编辑  收藏  举报