博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【bzoj3456】城市规划 容斥原理+NTT+多项式求逆
阅读量:5300 次
发布时间:2019-06-14

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

题目描述

求出n个点的简单(无重边无自环)无向连通图数目mod 1004535809(479 * 2 ^ 21 + 1).

输入

仅一行一个整数n(<=130000)

输出

仅一行一个整数, 为方案数 mod 1004535809.

样例输入

3

样例输出

4


题解

容斥原理+NTT+多项式求逆

设 $f_i$ 表示 $i$ 个点的简单无向连通图的数目,$g_i$ 表示 $i$ 个点的简单无向图的数目。

根据定义得 $g_i=2^{\frac{n(n-1}2}$ 。

对于 $f_i$ ,考虑容斥,用 $g_i$ 减去不连通的方案数。枚举不连通图中1号点所在连通块大小 $j$ ,则有:

$$f_i=g_i-\sum\limits_{j=1}^{i-1}C_{i-1}^{j-1}f_jg_{i-j}$$ 

将组合数展开,得:

$$f_i=g_i-\sum\limits_{j=1}^{i-1}\frac{(i-1)!}{(j-1)!(i-j)!}f_jg_{i-j}$$ 

两边同时除以 $(i-1)!$ ,整理得:

$$\frac{f_i}{(i-1)!}=\sum\limits_{j=1}^{i-1}\frac{f_j}{(j-1)!}\frac{g_{i-j}}{(i-j)!}$$ 

设:

$$F(x)=\sum\limits_{i=1}^{\infty}\frac{f_i}{(i-1)!} \\ G(x)=\sum\limits_{i=1}^{\infty}\frac{g_i}{(i-1)!} \\ H(x)=\sum\limits_{i=1}^{\infty}\frac{g_i}{i!}$$ 

注意到 $F(x)$ 、$H(x)$ 的常数项均为0,因此后面的那个式子相当于 $\sum\limits_{j=0}^iF(x)[j]H(x)[i-j]$ ,是一个卷积的形式。

因此有:

$$F(x)=G(x)-F(x)\times H(x)$$ 

化简得:

$$F(x)=\frac{G(x)}{H(x)+1}$$ 

剩下的就好办了,根据定义求出 $G(x)$ 和 $H(x)+1$ ,使用多项式求逆求出 $H(x)+1$ 的逆,再与 $G(x)$ 求乘法即可得到 $F(x)$ 。

最后的答案就是 $F(x)[n]\times(n-1)!$ 。

时间复杂度 $O(n\log n)$ 

#include 
#include
#include
#define N 262200#define mod 1004535809using namespace std;typedef long long ll;ll A[N] , B[N] , C[N] , t[N] , fac[N >> 1];inline ll pow(ll x , ll y){ ll ans = 1; while(y) { if(y & 1) ans = ans * x % mod; x = x * x % mod , y >>= 1; } return ans;}void ntt(ll *a , int n , int flag){ int i , j , k; for(i = k = 0 ; i < n ; i ++ ) { if(i > k) swap(a[i] , a[k]); for(j = n >> 1 ; (k ^= j) < j ; j >>= 1); } for(k = 2 ; k <= n ; k <<= 1) { ll wn = pow(3 , (mod - 1) / k); if(flag == -1) wn = pow(wn , mod - 2); for(i = 0 ; i < n ; i += k) { ll w = 1 , t; for(j = i ; j < i + (k >> 1) ; j ++ , w = w * wn % mod) t = w * a[j + (k >> 1)] % mod , a[j + (k >> 1)] = (a[j] - t + mod) % mod , a[j] = (a[j] + t) % mod; } } if(flag == -1) { k = pow(n , mod - 2); for(i = 0 ; i < n ; i ++ ) a[i] = a[i] * k % mod; }}void inv(ll *a , ll *b , int n){ if(n == 1) { b[0] = 1; return; } int i; inv(a , b , n >> 1); memcpy(t , a , sizeof(ll) * n); ntt(t , n << 1 , 1); ntt(b , n << 1 , 1); for(i = 0 ; i < n << 1 ; i ++ ) b[i] = b[i] * (2 - t[i] * b[i] % mod + mod) % mod; ntt(b , n << 1 , -1); memset(b + n , 0 , sizeof(ll) * n);}int main(){ int n , i , len = 1; scanf("%d" , &n); fac[0] = A[0] = 1; for(i = 1 ; i <= n ; i ++ ) { fac[i] = fac[i - 1] * i % mod; A[i] = pow(2 , (ll)i * (i - 1) / 2) * pow(fac[i] , mod - 2) % mod; B[i] = pow(2 , (ll)i * (i - 1) / 2) * pow(fac[i - 1] , mod - 2) % mod; } while(len <= n) len <<= 1; inv(A , C , len); ntt(B , len , 1); ntt(C , len , 1); for(i = 0 ; i < len ; i ++ ) B[i] = B[i] * C[i] % mod; ntt(B , len , -1); printf("%lld\n" , B[n] * fac[n - 1] % mod); return 0;}

 

 

转载于:https://www.cnblogs.com/GXZlegend/p/8596008.html

你可能感兴趣的文章
JavaScript之原生接口类设计
查看>>
query_phase_execution_exception
查看>>
MySQL进阶12-- 数据类型介绍: 数值型/字符型/日期型-- 正负溢出保护/枚举型/set型/时间戳...
查看>>
[ACM_水题] UVA 12502 Three Families [2人干3人的活后分钱,水]
查看>>
ThreadLocal的理解
查看>>
你不知道的CSS
查看>>
HashMap深度解析(一)
查看>>
Java跨平台原理
查看>>
批梯度下降和随机梯度下降的区别和代码实现
查看>>
android常见错误与问题
查看>>
[Scala] 快学Scala A1L1
查看>>
[转]Oracle DB 使用快速恢复区
查看>>
特性属性 @property
查看>>
Jmeter跨线程组传递变量
查看>>
UOJ #225.排队
查看>>
MS SQL Server2012中的IIF函数
查看>>
判断3389端口是否开启
查看>>
LINQ 入门
查看>>
不变集合 NSSet
查看>>
标准C程序设计七---54
查看>>