博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【bzoj3456】城市规划(多项式求逆+dp)
阅读量:5172 次
发布时间:2019-06-13

本文共 4112 字,大约阅读时间需要 13 分钟。

Description

\(~n~\)个点组成的有标号无向连通图的个数。\(~1 \leq n \leq 13 \times 10 ^ 4~\).

Solution

这道题的弱化版是, 其中\(n \leq 50\), 先来解决这个弱化版的题。考虑\(~dp~\),直接统计答案难以入手,于是考虑容斥。显然有,符合条件的方案数\(=\)所有方案数\(-\)不符合条件的方案数,而这个不符合条件的方案数就是图没有完全联通的情况。设\(~dp_i~\)表示\(~i~\)个点组成的合法方案数,考虑\(~1~\)号点的联通情况,易得

\[ dp_i = 2 ^ {i \choose 2} - \sum_{j = 1}^{i - 1} {dp_j \times {
{i - 1} \choose {j - 1}}} \times 2 ^ {
{i - j} \choose 2} \]
这是什么意思呢...枚举\(~1~\)号点所在的联通块大小\(~j~\), 可以知道这个联通块有\(~dp_j~\)种连法,除了这\(~j~\)个点,剩下的点可以随意连接,而这\(~j - 1~\)个点可以在\(~i - 1~\)个点中随意选择(因为强制选了\(~1~\)号点)。

那么这个简单版就已经解决了,时间复杂度\(~O(n ^ 2)~\), 而且要写高精度。博主很懒就不想写了。这个复杂度不是神威的话肯定是跑不过的。于是我们考虑优化,把上面的式子展开,可以得到

\[ dp_i = 2 ^ {i \choose 2} - \sum_{j = 1}^{i - 1} dp_j \times \frac{(i - 1)!}{(j - 1)!(i - j)! } \times {2 ^ {i - j \choose 2}} \]
同除\(~(i - 1) !~​\), 得
\[ \frac{dp_i}{(i - 1)!} = \frac{2 ^ {i \choose 2}}{(i - 1)!} - \sum_{j = 1}^{i - 1} \frac {dp_j \times {2 ^ {i - j \choose 2}}} {(j - 1)!(i - j)!} \]
观察一下,这个\(~ \frac{dp_i}{(i - 1)!} ~\)就是那个\(~\sum~\)式子的第\(~i~\)项, 移项得,
\[ \sum_{j = 1}^{i} \frac {dp_j}{(j - 1)!} \times \frac{2 ^ {i - j \choose 2}}{(i - j)!} = \frac{2 ^ {i \choose 2}}{(i - 1)!} \]
左边是很自然的一个卷积式子。令
\[ h = \sum_{i = 1}^{n} \frac{dp_i}{(i - 1)!} \times x^i~~, ~~g = \sum_{i = 0}^{n} \frac{2 ^ {i \choose 2}}{i!}\times x^i~~, ~~f = \sum_{i = 1}^{n} \frac{2 ^ {i \choose 2}}{(i - 1)!}\times x^i~~ \]
所以有\(~f = h * g\), 但是我们要求的是\(~h_n~\),转换一下就是\(~h = g * f ^ {-1}\), 要用到。

Code

#include
#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;}

转载于:https://www.cnblogs.com/LSTete/p/9575645.html

你可能感兴趣的文章
电脑屏幕保护眼睛
查看>>
有用的东西
查看>>
如何开启VMware串口
查看>>
数据库
查看>>
常见Struts、Hibernate、Spring、J2EE、ibatis、Oracle等开发框架架构图及其简介
查看>>
Java为何大行其道
查看>>
CFileDialog的使用方法简单介绍
查看>>
send,recv,sendto,recvfrom
查看>>
C#开发问题汇总
查看>>
Kettle
查看>>
[复习]Python基础回顾
查看>>
LNMP
查看>>
java 读写锁
查看>>
_itoa_s替换 itoa
查看>>
Nginx负载均衡
查看>>
【bzoj3456】城市规划(多项式求逆+dp)
查看>>
#ifdef 支持Mac #ifndef 支持Windows #if defined (Q_OS_WIN) 应该可以再两个系统通用
查看>>
linux源码中的核心数据结构
查看>>
EF执行SQL语句
查看>>
Ogre学习教程:Ogre1.8.1+VS2010环境配置2(转)
查看>>