题面

求有 \(n\) 个点的无向有标号连通图个数 . \((1 \le n \le 1.3 * 10^5)\)

题解

首先考虑 dp ... 直接算可行的方案数 , 容易算重复 .

我们用总方案数减去不可行的方案数就行了 (容斥)

令 \(f_i\) 为有 \(i\) 个点的无向有标号连通图个数 .

考虑 \(1\) 号点的联通块大小 , 联通块外的点之间边任意 但 不能与 \(1\) 有间接联系 .

那么就有

\[\displaystyle f_i = 2^{\binom i 2} - \sum_{j=1}^{i-1} f_j \times \binom {i-1}{j-1} \times 2^{\binom{i-j}{2}}
\]

这个可以直接用 CDQ分治FFT 求 , 但我不会 ...

那认真考虑一下这个式子 qwq

先展开组合数

\[\displaystyle f_i=2^{\binom{i}{2}} - \sum_{j=1}^{i-1} f_j \times \frac{(i-1)!}{(j-1)!(i-j)!} \times 2^{\binom {i-j}{2}}
\]

除去 \((i-1)!\)

\[\displaystyle \frac{f_i}{(i-1)!} = \frac{2^{\binom i 2}}{(i-1)!} - \sum_{j=1}^{i-1} \frac{f_j\times2^{\binom{i-j}{2}}}{(j-1)!(i-j)!}
\]

移项合并

\[\displaystyle \sum_{j=1}^{i} \frac{f_j \times 2^{\binom {i-j}{2}}}{(j-1)!\times(i-j)!} = \frac{2^{\binom i 2}}{(i-1)!}
\]

左边我们观察一下不难发现是一个卷积形式 .

令 \(\displaystyle A=\sum_{i=1}^{n} \frac{f_i}{(i-1)!} x^i\)

\(\displaystyle B=\sum_{i=0}^{n} \frac{2^{\binom {i}{2}}}{i!} x^i\)

\(\displaystyle C = \sum_{i=1}^{n} \frac{2^{\binom{i}{2}}}{(i-1)!} x^i\)

就有 \(A * B = C \Rightarrow A=C * B^{-1}\)

我们只需要求出 \(B\) 在 \(x^n\) 下的逆元就行了 qwq

怎么求呢 :

多项式求逆 :

如果 \(B\) 为 \(A\) 在 \(x^n\) 意义下的逆元 , 那么数学表达就是 :

\[A * B \equiv 1 \pmod {x^n}
\]

假设我们已经求出了\(B\) 在 \(\displaystyle x^{\frac{n}{2}}\) 的逆元 \(B'\) . (我们常常令 \(n\) 为 \(2^k\) )

\(\displaystyle A * B' \equiv 1 \pmod {x^\frac{n}{2}} \tag{1}\)

我们之前那个 \(x^{\frac{n}{2}}\) 意义下也成立 ... 就有

\[\displaystyle A * B \equiv 1 \pmod {x^{\frac{n}{2}}} \tag{2}
\]

让 \((2)-(1)\) 就有

\[B - B'\equiv 0 \pmod{x^{\frac n 2}}
\]

然后把它左右平方一下 (此处 \(x^\frac{n}{2}\) 也可平方成 \(x^n\) )

\[B^2 -2BB' +B'^2 \equiv 0 \pmod {x^{n}}
\]

乘上一个 \(A\) 就得到

\[B \equiv 2B' - A * B'^2 \pmod {x^n}
\]

然后递归求解就行了 .

那么复杂度就是 \(T(n) = T(\frac{n}{2}) + O(n \log n) =O(n \log n)\) ...

代码在这道题程序中有 ...

代码

/**************************************************************
Problem: 3456
User: DOFY
Language: C++
Result: Accepted
Time:11956 ms
Memory:107796 kb
****************************************************************/ #include <bits/stdc++.h>
#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std; typedef long long ll;
inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;} inline int read() {
int x = 0, fh = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1;
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return x * fh;
} void File() {
#ifdef zjp_shadow
freopen ("3456.in", "r", stdin);
freopen ("3456.out", "w", stdout);
#endif
} const int N = (1 << 21) + 5, Mod = 1004535809; ll fpm(ll x, int power) {
ll res = 1;
for (; power; power >>= 1, (x *= x) %= Mod)
if (power & 1) (res *= x) %= Mod;
return res;
} ll fac[N], ifac[N]; inline ll C(int n, int m) {
if (n < 0 || m < 0 || n < m) return 0;
return fac[n] * ifac[m] % Mod * ifac[n - m] % Mod;
} void Init(int maxn) {
fac[0] = ifac[0] = 1;
For (i, 1, maxn) fac[i] = fac[i - 1] * i % Mod;
ifac[maxn] = fpm(fac[maxn], Mod - 2);
Fordown (i, maxn - 1, 1) ifac[i] = ifac[i + 1] * (i + 1) % Mod;
} inline int Add(int a, int b) { return ((a += b) >= Mod) ? a - Mod : a; }
struct Number_Theory_Transform {
int pow3[N], invpow3[N];
inline void Init(int maxn) {
for (int i = 2; i <= maxn; i <<= 1)
pow3[i] = fpm(3, (Mod - 1) / i), invpow3[i] = fpm(pow3[i], Mod - 2);
} int n, rev[N];
inline void Get_Rev() {
int cnt = 0; for (int i = 1; i < n; i <<= 1) ++ cnt;
For (i, 0, n - 1) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (cnt - 1));
} void NTT(int P[], int opt) {
For (i, 0, n - 1) if (i < rev[i]) swap(P[i], P[rev[i]]);
for (int i = 2; i <= n; i <<= 1) {
int p = i >> 1, Wi = opt == 1 ? pow3[i] : invpow3[i];
for (int j = 0; j < n; j += i)
for (int k = 0, x = 1; k < p; ++ k, x = 1ll * x * Wi % Mod) {
int u = P[j + k], v = 1ll * x * P[j + k + p] % Mod;
P[j + k] = Add(u, v);
P[j + k + p] = Add(u, Mod - v);
}
}
if (opt == -1) {
int invn = fpm(n, Mod - 2);
For (i, 0, n - 1) P[i] = 1ll * P[i] * invn % Mod;
}
} int A[N], B[N];
void Mult(int a[], int b[], int c[], int len) {
for (n = 1; n <= len; n <<= 1); Get_Rev();
For (i, 0, n - 1) A[i] = a[i], B[i] = b[i]; NTT(A, 1); NTT(B, 1);
For (i, 0, n - 1) A[i] = 1ll * A[i] * B[i] % Mod;
NTT(A, -1); For (i, 0, n - 1) c[i] = A[i];
} void Get_Inv(int a[], int b[], int len) {
if (len == 1) { b[0] = fpm(a[0], Mod - 2); return ; }
Get_Inv(a, b, len >> 1); n = len << 1; Get_Rev();
For (i, 0, len - 1) A[i] = a[i], B[i] = b[i]; NTT(A, 1); NTT(B, 1);
For (i, 0, n - 1) A[i] = 1ll * A[i] * B[i] % Mod * B[i] % Mod;
NTT(A, - 1); For (i, 0, len - 1)
b[i] = Add(Add(b[i], b[i]), Mod - A[i]);
}
} T; int a[N], b[N], c[N], tmp[N], n; int Edge(int x, int nowmod) { return 1ll * x * (x - 1) / 2 % nowmod; } int main () {
File();
n = read();
T.Init(1 << 20); Init(n); For (i, 0, n)
b[i] = fpm(2, Edge(i, Mod - 1)) * ifac[i] % Mod; For (i, 0, n)
c[i] = fpm(2, Edge(i, Mod - 1)) * ifac[i - 1] % Mod; int len = 1; for (; len <= n; len <<= 1);
T.Get_Inv(b, tmp, len); T.Mult(tmp, c, a, len); printf ("%lld\n", 1ll * a[n] * fac[n - 1] % Mod); return 0;
}

BZOJ 3456: 城市规划 与 多项式求逆算法介绍(多项式求逆, dp)的更多相关文章

  1. [BZOJ 3456]城市规划(cdq分治+FFT)

    [BZOJ 3456]城市规划(cdq分治+FFT) 题面 求有标号n个点无向连通图数目. 分析 设\(f(i)\)表示\(i\)个点组成的无向连通图数量,\(g(i)\)表示\(i\)个点的图的数量 ...

  2. bzoj 3456 城市规划 —— 分治FFT / 多项式求逆 / 指数型生成函数(多项式求ln)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3456 首先考虑DP做法,正难则反,考虑所有情况减去不连通的情况: 而不连通的情况就是那个经典 ...

  3. BZOJ 3456: 城市规划 [多项式求逆元 组合数学 | 生成函数 多项式求ln]

    3456: 城市规划 题意:n个点组成的无向连通图个数 以前做过,今天复习一下 令\(f[n]\)为n个点的无向连通图个数 n个点的完全图个数为\(2^{\binom{n}{2}}\) 和Bell数的 ...

  4. bzoj 3456 城市规划——分治FFT / 多项式求逆 / 多项式求ln

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3456 分治FFT: 设 dp[ i ] 表示 i 个点时连通的方案数. 考虑算补集:连通的方 ...

  5. BZOJ 3456 城市规划 ( NTT + 多项式求逆 )

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3456 题意: 求出\(n\)个点的简单(无重边无自环)无向连通图的个数.(\(n< ...

  6. bzoj 3456 城市规划 无向简单连通图个数 多项式求逆

    题目大意 求n个点的无向简单连通图个数 做法1 \(f[i]\)表示i个点的无向简单连通图个数 \(g[i]=2^{\frac {i*(i-1)}{2}}\)表示i个点的无向简单图个数(不要求连通) ...

  7. BZOJ 3456: 城市规划 多项式求逆

    Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了.  刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接 ...

  8. BZOJ 3456: 城市规划(dp+多项式求逆)

    传送门 解题思路 这道题就是求带标号的无向连通图个数,首先考虑\(O(n^2)\)的做法,设\(f_i\)表示有\(i\)个节点的无向连通图个数,那么考虑容斥,先把所有的无向图求出,即为\(2^{C( ...

  9. bzoj 3456: 城市规划【NTT+多项式求逆】

    参考:http://blog.miskcoo.com/2015/05/bzoj-3456 首先推出递推式(上面的blog讲的挺清楚的),大概过程是正难则反,设g为n个点的简单(无重边无自环)无向图数目 ...

随机推荐

  1. CentOS 7安装指南

    CentOS 7安装指南(U盘版) 一.准备阶段 1.下载CentOS7镜像文件(ISO文件)到自己电脑,官网下载路径: http://isoredirect.centos.org/centos/7/ ...

  2. Unity Profiler的使用

    选中Development Build.Autoconnect Profiler和Script Debugging三个选项,如下图所示. 点击Build And Run按钮,将会编译项目并安装APK到 ...

  3. Vysor Pro破解助手

    Vysor更新到1.7.7版本后,原来提供的VysorPro助手无法正常破解了. 针对新版本的改动,更新了一下Vysor破解助手,支持破解Vysor 1.6.6和Vysor1.7.7之间的版本. Vy ...

  4. python(day16)内置函数,匿名函数

    # add = lambda x,y:x+y # print(add(1,2)) # dic={'k1':10,'k2':100,'k3':30} # def func(key): # return ...

  5. PM过程能力成熟度2级

    当PM意识到自己不再是程序员后,就会在项目管理方面,逐渐达到过程能力成熟度1级.尽管这种亲身经历会带给PM管理的信心,但从项目的层面来说,整体还是混沌的,PM在经历过1级的阶段性胜利后,将面临更多的问 ...

  6. telnet操作memcache

    1.使用方法 1. 连接到memcached telnet 192.168.1.100 11211 add name 0 60 5     [说明 add 是指令名  name 是key的名字 (是以 ...

  7. canvas save()和canvas restore()状态的保存和恢复使用方法及实例

    canvas.save()用来保存先前状态的 canvas.restore()用来恢复之前保存的状态 注:两种方法必须搭配使用,否则没有效果 <!DOCTYPE html> <htm ...

  8. (七)Create an Index

    Now let’s create an index named "customer" and then list all the indexes again: 现在让我们创建一个名 ...

  9. 日版iphone5 SB 配合REBELiOS卡贴破解电信3G步骤

    1.插入贴膜卡和sim卡:进入“设置—电话—sim卡应用程序”选择CDMA电信解锁: 2.越狱设备,添加cydia.gpplte.com源,安装“6S/6/5S/5C/5电信新补丁”: 3.打卡gpp ...

  10. 调参必备---GridSearch网格搜索

    什么是Grid Search 网格搜索? Grid Search:一种调参手段:穷举搜索:在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果.其原理就像是在数组里找最 ...