BZOJ3456城市规划

BZOJ3456

http://www.lydsy.com/JudgeOnline/problem.php?id=3456

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
const int mod=1004535809,maxn=1<<18|1;
int p[maxn],gn[233];
int n;
int fac[maxn],inv[maxn],tp[maxn];
inline int fp(int a,int b){
	int res=1;
	while(b){
		if(b&1)res=1ll*res*a%mod;
		a=1ll*a*a%mod;b>>=1;
	}
	return res;
}
inline void init(){
	for(register int i=0;i<=23;++i)gn[i]=fp(3,(mod-1)/(1<<(i+1)));
	fac[0]=1;for(register int i=1;i<=n+1;++i)fac[i]=1ll*fac[i-1]*i%mod;
	inv[1]=1;for(register int i=2;i<=n+1;++i)inv[i]=mod-1ll*mod/i*inv[mod%i]%mod;
	inv[0]=1;for(register int i=1;i<=n+1;++i)inv[i]=1ll*inv[i]*inv[i-1]%mod;
	for(register int i=0;i<=n+1;++i)tp[i]=fp(2,(1ll*i*(i-1)/2)%(mod-1));
}
struct poly{
	int a[maxn],n;
	poly(){memset(a,0,sizeof(a));}
	inline int &operator[](const int x){return a[x];}
	inline void ntt(int d,int f){
		for(register int i=0;i<d;++i)if(i<p[i])swap(a[i],a[p[i]]);
		for(register int i=1,t=0,w,v;i<d;i<<=1,++t){
			for(register int j=0;j<d;j+=(i<<1)){
				w=1;
				for(register int k=j;k<i+j;++k,w=1ll*w*gn[t]%mod)
					v=1ll*w*a[i+k]%mod,a[i+k]=(a[k]-v+mod)%mod,a[k]=(a[k]+v)%mod;
			}
		}
		if(f==1)return;
		reverse(a+1,a+d);
		register int ny=fp(d,mod-2);
		for(register int i=0;i<d;++i)a[i]=1ll*a[i]*ny%mod;
	}
	friend inline poly operator*(poly &A,poly &B){
		register poly res;res.n=A.n+B.n;int d,lg2;
		for(d=1,lg2=0;d<=res.n;d<<=1)++lg2;
		for(register int i=0;i<d;++i)p[i]=(p[i>>1]>>1)^((i&1)<<(lg2-1));
		A.ntt(d,1);B.ntt(d,1);
		for(register int i=0;i<d;++i)res[i]=1ll*A[i]*B[i]%mod;
		res.ntt(d,-1);A.ntt(d,-1);B.ntt(d,-1);
		return res;
	}
}A,B,tmp,invA,Ans;
inline void poly_inv(int deg){
	if(deg==1){
		invA[0]=1;invA[0]=fp(A[0],mod-2);
		return ;
	}
	poly_inv((deg+1)>>1);
	register int d=1,lg2=0;for(d=1;d<=(deg<<1);d<<=1)++lg2;
	for(register int i=0;i<d;++i)p[i]=(p[i>>1]>>1)^((i&1)<<(lg2-1));
	for(register int i=0;i<d;++i)tmp[i]=i<deg?A[i]:0;
	for(register int i=(deg+1)>>1;i<d;++i)invA[i]=0;
	invA.ntt(d,1);tmp.ntt(d,1);
	for(register int i=0;i<d;++i)invA[i]=(mod+2ll*invA[i]%mod-1ll*invA[i]*invA[i]%mod*tmp[i]%mod)%mod;
	invA.ntt(d,-1);invA.n=deg-1;
}
int main(){
	scanf("%d",&n);init();A.n=B.n=n;
	for(register int i=0;i<=n;++i)A[i]=1ll*tp[i]*inv[i]%mod;
	for(register int i=1;i<=n;++i)B[i]=1ll*tp[i]*inv[i-1]%mod;
	poly_inv(n+1);
	printf("%d\n",1ll*(invA*B)[n]*fac[n-1]%mod);
	return 0;
}

  

原文地址:https://www.cnblogs.com/Stump/p/8454369.html

时间: 2024-10-09 00:02:30

BZOJ3456城市规划的相关文章

[BZOJ3456]城市规划(生成函数+多项式求逆+多项式求ln)

城市规划 时间限制:40s      空间限制:256MB 题目描述 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了.  刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一样, 那么这两个方案就是不同的, 否则就是相同的. 现在你需要求出一共有多少不同的方案.  好了, 这就

BZOJ3456 城市规划 【分治NTT】

题目链接 BZOJ3456 题解 据说这题是多项式求逆 我太弱不会QAQ,只能\(O(nlog^2n)\)分治\(NTT\) 设\(f[i]\)表示\(i\)个节点的简单无向连通图的数量 考虑转移,直接求不好求,我们知道\(n\)个点无向图的数量是\(2^{{n \choose 2}}\)的,考虑用总数减去不连通的 既然图不连通,那么和\(1\)号点联通的点数一定小于\(n\),我们枚举和\(1\)号点所在联通块大小,就可以得到式子: \[f[n] = 2^{{n \choose 2}} - \

[bzoj3456]城市规划——分治FFT

题目大意: 求n个点的带标号简单无向联通图的数目. 思路: 嗯多项式求逆还不会,到时候会了应该会补吧. 这种和图计数有关的题目一般都是考虑反面计数或者是容斥什么的. 考虑枚举一号点的连通块的大小,然后用总方案数减去这些方案数. 可以得到递推式: \[ f_{i}=2^{i\choose 2}-\sum_{j=1}^{i-1}{i-1\choose j-1}\times f_{j}\times 2^{i-j\choose2} \] 后面的式子可以化为卷积的形式: \[ f_{i}=2^{i\cho

bzoj3456 城市规划

Description 求含有n个点有标号的无向联通图的个数(没有重边),n<=130000 Input 3 Output 4 正解:$分治FFT$/多项式求逆. 并没有权限号,但是某$oj$里有这道题.. 我们考虑递推,$f[i]$表示$i$个点的联通图个数,那么用总数减去不合法的数量. 考虑枚举$1$号点所在的联通块的点数,那么我们可以得到: $f[n]=2^{\binom{n}{2}}-\sum_{i=1}^{n-1}f[i]*\binom{n-1}{i-1}*2^{\binom{n-i}

[bzoj3456]城市规划:多项式,分治

Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一样, 那么这两个方案就是不同的, 否则就是相同的. 现在你需要求出一共有多少不同的方案. 好了, 这就是困扰阿狸的问题. 换句话说, 你需要求出n个点的

模板记录

NTT: namespace NTT { int n,m,l,r[N]; void NTT(int *a,int f) { 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=q_pow(pr,phi/(i<<1)); if(f==-1) wn=q_pow(wn,mod-2); for(int p=i<<1,j=0;j<n;j+=p

BZOJ3456:城市规划——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=3456 求出n个点的简单(无重边无自环)无向连通图数目 模数很熟悉,先敲一个MTT. 然后通过推导式子就做完啦! 我觉得就算怎么讲也没有下面这一位好:http://blog.miskcoo.com/2015/05/bzoj-3456 另外多项式求逆:http://blog.miskcoo.com/2015/05/polynomial-inverse 至少我学到了:当你有个卷积知道答案,求卷积的一项

【bzoj3456】城市规划(多项式求逆+dp)

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

【BZOJ3456】【CDQ分治+FNT】城市规划

试题来源 2013中国国家集训队第二次作业 问题描述 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一样, 那么这两个方案就是不同的, 否则就是相同的. 现在你需要求出一共有多少不同的方案. 好了, 这就是困扰阿狸的问题.