BZOJ 3456: 城市规划

3456: 城市规划

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 640  Solved: 352
[Submit][Status][Discuss]

Description

刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了.
 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一样, 那么这两个方案就是不同的, 否则就是相同的. 现在你需要求出一共有多少不同的方案.
 好了, 这就是困扰阿狸的问题. 换句话说, 你需要求出n个点的简单(无重边无自环)无向连通图数目.
 由于这个数字可能非常大, 你只需要输出方案数mod 1004535809(479 * 2 ^ 21 + 1)即可.

Input

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

Output

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

Sample Input

3

Sample Output

4

HINT

对于 100%的数据, n <= 130000

Source

分析:

有两种方法:

一种是直接计算方案数

一种是用总的方案数减去不合法的方案数

如果直接计算:

我们定义$f[i]$为点数为$i$的无向连通图的数量,我们考虑已经计算出了前$n-1$个点的答案,考虑新加入第$n$号节点,这个$n$号节点一定是联通了之前的若干个联通块,所以我们枚举$1$号节点所在的联通块的大小$s$,那么$n$号节点和$1$号节点所在的联通块联通的方案有$2^s-1$种,这个联通块的方案为$f[s]$,剩下的$n-s$个点就是一个子问题了也就是$f[n-s]$,那么最后的式子就是:$\sum _{s=1}^{n-1} \textrm{C}_{n-2}^{s-1}f[n-s]f[s](2^s-1)$

发现这是一个分治$NTT$,然而复杂度貌似是$O(Nlog^2N)$的...

另一种计算补集的方法的复杂度就优秀了一点:

定义$f[i]$代表点数为$i$的无向联通图的数量,考虑总的可能出现在图中的边有$\textrm{C}_{n}^{2}$种,那么生成图的数量就是$2^{\textrm{C}_{n}^{2}}$,现在我们考虑不合法的方案:依旧考虑$1$号节点所在的联通块大小为$s$,那么其他的$n-s$个点的子图随便排列,也就是说,不合法的为$\sum _{j=1}^{i-1}f[j]\textrm{C}_{i-1}^{j-1}2^{\textrm{C}_{i-j}^{2}}$...

两边同时除以$(i-1)!$:

$\frac{ f[i] }{ (i-1)! }=\frac{ 2^{\textrm{C}_{i}^{2}} }{ (i-1)! }-\frac{\sum _{j=1}^{i-1}f[j]\textrm{C}_{i-1}^{j-1}2^{\textrm{C}_{i-j}^{2}}}{(i-1)!}$

最后的式子长成酱紫:

$\sum_{j=1}^{i}\frac{f[j]}{(j-1)!}*\frac{ 2^{ \textrm{C}_{i-j}^{2} } }{(i-j)!}=\frac{2^{\textrm{C}_{i}^{2}}}{(i-1)!}$

我们令$A=\sum_{i=1}^{n}\frac{f[i]}{(i-1)!}*x^i$

$B=\sum_{i=0}^{n}\frac{2^{\textrm{C}_{i}^{2}}}{i!}*x^i$

$C=\sum_{i=1}^{n}\frac{2^{\textrm{C}_{i}^{2}}}{(i-1)!}*x^i$

那么$A*B=C$,我们可以得出$A=C*B^{-1}$,所以求个逆$NTT$一下就好了...

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
using namespace std;

const int maxn=1000000+5,mod=1004535809,G=3;

int n,m,L,N,R[maxn],a[maxn],b[maxn],c[maxn],d[maxn],fac[maxn],inv[maxn];

inline int power(int x,long long y){
	int res=1;
	while(y){
		if(y&1) res=1LL*res*x%mod;
		x=1LL*x*x%mod,y>>=1;
	}
	return res;
}

inline void NTT(int *a,int f,int n,int L){
	for(int i=0;i<n;i++)
		R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
	for(int i=0;i<n;i++)
		if(i<R[i]) swap(a[i],a[R[i]]);
	for(int i=1;i<n;i<<=1){
		int wn=power(G,(mod-1)/(i<<1));
		if(f==-1) wn=power(wn,mod-2);
		for(int j=0;j<n;j+=(i<<1)){
			int w=1;
			for(int k=0;k<i;k++,w=1LL*w*wn%mod){
				int x=a[j+k],y=1LL*a[j+k+i]*w%mod;
				a[j+k]=(x+y)%mod;
				a[j+k+i]=(x-y+mod)%mod;
			}
		}
	}
	if(f==-1){
		int tmp=power(n,mod-2);
		for(int i=0;i<n;i++)
			a[i]=1LL*a[i]*tmp%mod;
	}
}

inline void inverse(int *a,int *b,int n,int L){
	if(n==1){
		b[0]=power(a[0],mod-2);return;
	}
	inverse(a,b,n>>1,L-1);
	memcpy(d,a,n*sizeof(int));
	memset(d+n,0,n*sizeof(int));
	NTT(d,1,n<<1,L+1);NTT(b,1,n<<1,L+1);
	for(int i=0;i<n<<1;i++) b[i]=1LL*b[i]*((2-1LL*d[i]*b[i]%mod+mod)%mod)%mod;
	NTT(b,-1,n<<1,L+1);
	memset(b+n,0,n*sizeof(int));
}

signed main(void){
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	memset(c,0,sizeof(c));
	scanf("%d",&n);fac[0]=1;
	for(int i=1;i<=n;i++) fac[i]=1LL*fac[i-1]*i%mod;
	inv[n]=power(fac[n],mod-2);
	for(int i=n-1;i>=0;i--) inv[i]=1LL*inv[i+1]*(i+1)%mod;
	m=n<<1;for(N=1;N<=m;N<<=1) L++;a[0]=1;
	for(int i=1;i<=n;i++) a[i]=1LL*power(2,1LL*i*(i-1)/2)*inv[i]%mod;
	for(int i=1;i<=n;i++) c[i]=1LL*power(2,1LL*i*(i-1)/2)*inv[i-1]%mod;
	inverse(a,b,N,L);
	NTT(b,1,N,L),NTT(c,1,N,L);
	for(int i=0;i<N;i++) b[i]=1LL*b[i]*c[i]%mod;
	NTT(b,-1,N,L);
	printf("%d\n",(int)(1LL*b[n]*fac[n-1]%mod));
	return 0;
}

  



By NeighThorn

时间: 2024-10-25 00:16:25

BZOJ 3456: 城市规划的相关文章

BZOJ 3456 城市规划 快速傅里叶变换

题目大意:求n个点的无向简单连通图个数,n≤1.3?105 递推式:fi=2C2i?∑i?1j=1fj?Cj?1i?1?2C2i?j 推导戳这里 然后两侧同除(i?1)!得到: fi(i?1)!=2C2i(i?1)!?∑i?1j=1fj?2C2i?j(j?1)!?(i?j)! ∑ij=1fj?2C2i?j(j?1)!?(i?j)!=2C2i(i?1)! ∑ij=1fj(j?1)!?2C2i?j(i?j)!=2C2i(i?1)! 这显然是一个卷积的形式 然后我们令: A=∑ni=1fi(i?1)!

BZOJ 3456 城市规划 多项式求ln

题意:链接 方法:多项式求ln 解析: 毒瘤题的倒数第二个- -! md毒瘤题都做完后再回来写题解真是爽歪歪 先看这道题怎么做. 首先一个简单无向图的边的个数是C(n,2),然后那么我们的选择就有2C(n,2)种. 然后我们再考虑简单无向连通图的方案数为fi. f[i]=2C(i,2)?∑i?1j=1f[j]?C(i?1,j?1)?2C(i?j,2) 上面的式子其实没啥卵用- 现在我们这么来考虑. 看如上大爷给出的PPT. 其实这个正体现了划分和被划分的关系. 对于简单无向图来说,简单无向连通图

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

参考:http://blog.miskcoo.com/2015/05/bzoj-3456 首先推出递推式(上面的blog讲的挺清楚的),大概过程是正难则反,设g为n个点的简单(无重边无自环)无向图数目,显然边数是\( C_{n}^{2} \),所以\( g(n)=2^{C_{n}^{2}} \),那么f[n]=g[n]-n个点的简单(无重边无自环)无向不连通图数目,后面那部分可以枚举1所在联通块的1点数,当这个块有i个点时,方案数为从n-1个点中选出i-1个(减去点1)* f[i](这i个点组成

【BZOJ 3456】 3456: 城市规划 (NTT+多项式求逆)

3456: 城市规划 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 658  Solved: 364 Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一

【bzoj 3456】城市规划

好像欧爷很久以前就考过这道题了,然而我这个幼儿园小同学到现在才写 题意 求 $n$ 个点无标号简单无向连通图个数. 题解 方法1 原文地址:https://www.cnblogs.com/scx2015noip-as-php/p/bzoj3456.html

BZOJ 3456 NTT图的计数 容斥

思路: RT 懒得写了 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N=(1<<18)+5,mod=1004535809; int tmp[N],R[N],fac[N],A[N],B[N],C[N],niB[N]; int pow(ll x,ll y){

bzoj 3456

有两种推导方法: 第一种: 设状态$f(i)$表示有$i$个点的无向连通图个数,$g(i)$表示有$i$个点的无向图个数,那么显然$f(n)$即为我们所求,而$g(i)=2^{\frac{i(i-1)}{2}}$ 于是写出一个递推:枚举$1$号点所在的连通块,可得:$g(n)=\sum_{i=1}^{n}C_{n-1}^{i-1}f(i)g(n-i)$ 这已经很像一个卷积了,那么我们进一步展开组合数,也就是: $g(n)=\sum_{i=1}^{n}\frac{(n-1)!}{(n-i)!(i-

多项式求ln,求exp,开方,快速幂 学习总结

按理说Po姐姐三月份来讲课的时候我就应该学了 但是当时觉得比较难加上自己比较懒,所以就QAQ了 现在不得不重新弄一遍了 首先说多项式求ln 设G(x)=lnF(x) 我们两边求导可以得到G'(x)=F‘(x)/F(x) 则G(x)就是F’(x)/F(x)的积分 我们知道多项式求导和积分是O(n)的,多项式求逆是O(nlogn)的 所以总时间复杂度O(nlogn) 多项式求ln一般解决的问题是这样的 设多项式f表示一些奇怪的东西,由一些奇怪的东西有序组成的方案为 f^1+f^2+f^3…… 化简之

多项式求逆 学习总结

感觉蒟蒻现在学多项式求逆貌似有些晚了 不过真的很有意思了(然而省选的时候自己还在玩泥巴什么也不会 多项式求逆是基于倍增的 假设我们知道 h(x)f(x)=1(mod x^n) 移项得 (h(x)*f(x)-1)=0(mod x^n) 两边同时求平方得 h(x)^2*f(x)^2 - 2*h(x)*f(x) +1 = 0 (mod x^2n) 设g(x)*f(x)=1(mod x^2n) 两边同时乘以g(x)可以得 h(x)^2*f(x) -2*h(x) + g(x) =0 (mod x^2n)