【bzoj3456】城市规划(多项式求逆+dp)
Description
求\(~n~\)个点组成的有标号无向连通图的个数。\(~1 \leq n \leq 13 \times 10 ^ 4~\).
Solution
这道题的弱化版是poj1737, 其中\(n \leq 50\), 先来解决这个弱化版的题。考虑\(~dp~\),直接统计答案难以入手,于是考虑容斥。显然有,符合条件的方案数\(=\)所有方案数\(-\)不符合条件的方案数,而这个不符合条件的方案数就是图没有完全联通的情况。设\(~dp_i~\)表示\(~i~\)个点组成的合法方案数,考虑\(~1~\)号点的联通情况,易得
\]
这是什么意思呢...枚举\(~1~\)号点所在的联通块大小\(~j~\), 可以知道这个联通块有\(~dp_j~\)种连法,除了这\(~j~\)个点,剩下的点可以随意连接,而这\(~j - 1~\)个点可以在\(~i - 1~\)个点中随意选择(因为强制选了\(~1~\)号点)。
那么这个简单版就已经解决了,时间复杂度\(~O(n ^ 2)~\), 而且要写高精度。博主很懒就不想写了。这个复杂度不是神威的话肯定是跑不过的。于是我们考虑优化,把上面的式子展开,可以得到
\]
同除\(~(i - 1) !~\), 得
\]
观察一下,这个\(~ \frac{dp_i}{(i - 1)!} ~\)就是那个\(~\sum~\)式子的第\(~i~\)项, 移项得,
\]
左边是很自然的一个卷积式子。令
\]
所以有\(~f = h * g\), 但是我们要求的是\(~h_n~\),转换一下就是\(~h = g * f ^ {-1}\), 要用到多项式求逆。
Code
#include<bits/stdc++.h>
#define For(i, j, k) for (int i = j; i <= k; ++i)
#define Forr(i, j, k) for (int i = j; i >= k; --i)
using namespace std;
inline void File() {
freopen("bzoj3456.in", "r", stdin);
freopen("bzoj3456.out", "w", stdout);
}
const int N = (1 << 20) + 10, mod = 1004535809;
int a[N], b[N], c[N], fac[N], inv[N], n;
int powg[N], invg[N], rev[N], siz, p[N], q[N];
inline int qpow(int a, int b) {
static int res;
for (res = 1; b; b >>= 1, a = 1ll * a * a % mod)
if (b & 1) res = 1ll * res * a % mod;
return res;
}
inline void Init(int n) {
fac[0] = inv[0] = 1;
For(i, 1, n) fac[i] = 1ll * i * fac[i - 1] % mod;
inv[n] = qpow(fac[n], mod - 2);
Forr(i, n - 1, 0) inv[i] = 1ll * (i + 1) * inv[i + 1] % mod;
}
inline int add(int x, int y) { return (x += y) >= mod ? x - mod : x; }
inline void Init_pow(int n) {
int g = qpow(3, mod - 2);
for (int i = 1; i <= n; i <<= 1) {
powg[i] = qpow(3, (mod - 1) / i);
invg[i] = qpow(g, (mod - 1) / i);
}
}
inline void Init_rev(int n) {
int bit = 0; for (siz = 1; siz <= n; siz <<= 1) ++ bit;
For(i, 0, siz - 1) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));
}
inline void NTT(int *a, int flag) {
For(i, 0, siz - 1) if (rev[i] > i) swap(a[rev[i]], a[i]);
for (int i = 2; i <= siz; i <<= 1) {
int wn = flag > 0 ? powg[i] : invg[i];
for (int j = 0; j < siz; j += i) {
int w = 1;
for (int k = 0; k < i >> 1; w = 1ll * w * wn % mod, ++ k) {
int x = a[j + k], y = 1ll * w * a[j + k + (i >> 1)] % mod;
a[k + j] = add(x, y), a[k + j + (i >> 1)] = add(x, mod - y);
}
}
}
if (flag == -1) {
int g = qpow(siz, mod - 2);
For(i, 0, siz - 1) a[i] = 1ll * a[i] * g % mod;
}
}
inline void Inv(int *a, int *b, int len) { // b is the inv of a
if (len == 1) return (void) (b[0] = qpow(a[0], mod - 2));
Inv(a, b, len >> 1), Init_rev(len);
For(i, 0, len - 1) p[i] = a[i], q[i] = b[i];
NTT(p, 1), NTT(q, 1);
For(i, 0, siz - 1) p[i] = 1ll * q[i] * q[i] % mod * p[i] % mod;
NTT(p, -1);
For(i, 0, len - 1) b[i] = add(2 * b[i] % mod, mod - p[i]);
}
int main() {
File();
Init(N - 5), Init_pow(1 << 20);
scanf("%d", &n);
For(i, 0, n) b[i] = 1ll * inv[i] * qpow(2, 1ll * (i - 1) * i / 2 % (mod - 1)) % mod;
For(i, 1, n) c[i] = 1ll * inv[i - 1] * qpow(2, 1ll * (i - 1) * i / 2 % (mod - 1)) % mod;
Init_rev(n); Inv(b, a, siz);
NTT(a, 1), NTT(c, 1);
For(i, 0, siz - 1) a[i] = 1ll * a[i] * c[i] % mod;
NTT(a, -1);
int ans = 1ll * a[n] * fac[n - 1] % mod;
printf("%d", ans);
return 0;
}
【bzoj3456】城市规划(多项式求逆+dp)的更多相关文章
- BZOJ 3456: 城市规划 与 多项式求逆算法介绍(多项式求逆, dp)
题面 求有 \(n\) 个点的无向有标号连通图个数 . \((1 \le n \le 1.3 * 10^5)\) 题解 首先考虑 dp ... 直接算可行的方案数 , 容易算重复 . 我们用总方案数减 ...
- BZOJ 3456: 城市规划 多项式求逆
Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接 ...
- 【BZOJ3456】城市规划 多项式求逆
[BZOJ3456]城市规划 Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得 ...
- BZOJ 3456: 城市规划 [多项式求逆元 DP]
题意: 求出n个点的简单(无重边无自环)无向连通图数目.方案数mod 1004535809(479 * 2 ^ 21 + 1)即可. n<=130000 DP求方案 g(n) n个点所有图的方案 ...
- bzoj 3456 城市规划 多项式求逆+分治FFT
城市规划 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1091 Solved: 629[Submit][Status][Discuss] Desc ...
- bzoj3456 城市规划 多项式求In
\(n\)个点的无向联通图的个数 打着好累啊 一定要封装一个板子 记\(C(x)\)为无向图个数的指数型生成函数,\(C(0) = 1\) 记\(G(x)\)为无向联通图个数的指数型生成函数,\(G( ...
- [BZOJ3456]城市规划:DP+NTT+多项式求逆
写在前面的话 昨天听吕老板讲课,数数题感觉十分的神仙. 于是,ErkkiErkko这个小蒟蒻也要去学数数题了. 分析 Miskcoo orz 带标号无向连通图计数. \(f(x)\)表示\(x\)个点 ...
- 【BZOJ3456】轩辕朗的城市规划 无向连通图计数 CDQ分治 FFT 多项式求逆 多项式ln
题解 分治FFT 设\(f_i\)为\(i\)个点组成的无向图个数,\(g_i\)为\(i\)个点组成的无向连通图个数 经过简单的推导(枚举\(1\)所在的连通块大小),有: \[ f_i=2^{\f ...
- BZOJ3456 城市规划 【多项式求逆】
题目链接 BZOJ3456 题解 之前我们用分治\(ntt\)在\(O(nlog^2n)\)的复杂度下做了这题,今天我们使用多项式求逆 设\(f_n\)表示\(n\)个点带标号无向连通图数 设\(g_ ...
随机推荐
- vue实现双向数据绑定之Object.defineProperty()篇
前言 vue.js中使用ES5的Object.defineProperty()实现数据的双向绑定 Object.defineProperty()原理 Object.defineProperty()可以 ...
- 打印module查看参数
module1下的index.js require('./test2') main.js require('./module1')和require('./module2') 打印每个文件的module ...
- 从 Aliyun 经典网络迁移到 Aliyun VPC 网络
由于阿里云策略问题,要求用户从经典网络中全部迁出,搬迁到他们设置的 VPC 网络中.这里的 VPC 大概指的是逻辑上的一个虚拟局域网.即使是实际上你的机器垮机房在阿里云的不同机房.但是他们仍然能从逻辑 ...
- saltstack二
配置管理 haproxy的安装部署 haproxy各版本安装包下载路径https://www.haproxy.org/download/1.6/src/,跳转地址为http,改为https即可 创建相 ...
- AVL树,红黑树
AVL树 https://baike.baidu.com/item/AVL%E6%A0%91/10986648 在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高 ...
- Fiddler 学习笔记---命令、断点
输入命令框: 1 输入 ?51testing 高亮显示对应记录 2 >10 选择body大于10的记录 3 <10 选择body<10的记录 4 =200 选择result=200 ...
- vue動畫和過渡
過渡: 插入.更新和溢出DOM時,提供不同的方式應用過渡效果: vue提供內置的封裝組件,用於包裹要實現過渡效果的內容. <transition name="a">&l ...
- vue2 mint-ui loadmore(下拉刷新)
<template> <div class="page-loadmore"> <h1 class="page-title"> ...
- vue-cli: preset预设
preset:预设 vue create demo01 过程中,会保存预设,自动保存着 .vuerc 文件中 .vuerc 文件的位置:C:\Users\Administrator C:\Users\ ...
- python 读取csv 数据并画图分析
数据源 : https://pan.baidu.com/s/1eR593Uy 密码: yqjh python环境 python3 #encoding: utf-8 import csv impo ...