• [BZOJ3456] 城市规划


    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

    Solution

    (f(i))(i)个点的题目所求的答案,(g(i))(i)个点随便连的方案数,那么我们枚举(1)号点所在联通块的大小,可得:

    [g(n)=sum_{i=1}^nf(i)inom{n-1}{i-1}g(n-i)=2^{inom{n}{2}}=2^{n(n-1)/2} ]

    容易知道这样可以不重不漏的算到所有状态。

    我们把(g)带进去:

    [2^{n(n-1)/2}=sum_{i=1}^nf(i)inom{n-1}{i-1}2^{inom{n-i}{2}} ]

    两边除以((n-1)!)

    [frac{2^{n(n-1)/2}}{(n-1)!}=sum_{i=1}^nfrac{f(i)}{(i-1)!} imes frac{2^{inom{n-i}{2}}}{(n-i)!} ]

    注意到这是个卷积的形式,用生成函数表示一下:

    [A(x)=sum_{n=0}^inftyfrac{2^{n(n-1)/2}}{(n-1)!}x^n\ B(x)=sum_{n=0}^inftyfrac{2^{n(n-1)/2}}{n!}x^n\ F(x)=sum_{n=0}^inftyfrac{f(i)}{(n-1)!}x^n ]

    那么:

    [A(x)=F(x)B(x),F(x)=A(x)B^{-1}(x) ]

    那么直接套多项式求逆的板子就好了。

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    #define lf double
    #define ll long long 
    
    const int maxn = 6e5+10;
    const int inf = 1e9;
    const lf eps = 1e-8;
    const int mod = 1004535809;
    
    int n,w[maxn],rw[maxn],pos[maxn],f[maxn],a[maxn],b[maxn],c[maxn],mxn,N,bit,fac[maxn],ifac[maxn],g[maxn];
    
    int qpow(int aa,int x) {
    	int res=1;
    	for(;x;x>>=1,aa=1ll*aa*aa%mod) if(x&1) res=1ll*res*aa%mod;
    	return res;
    }
    
    void prepare() {
    	w[0]=1,w[1]=qpow(3,(mod-1)/mxn);
    	for(int i=2;i<=mxn;i++) w[i]=1ll*w[i-1]*w[1]%mod;
    	rw[0]=1,rw[1]=qpow(qpow(3,mod-2),(mod-1)/mxn);
    	for(int i=2;i<=mxn;i++) rw[i]=1ll*rw[i-1]*rw[1]%mod;
    }
    
    void ntt(int *r,int op) {
    	for(int i=1;i<N;i++) if(pos[i]>i) swap(r[i],r[pos[i]]);
    	for(int i=1,d=mxn>>1;i<N;i<<=1,d>>=1) 
    		for(int j=0;j<N;j+=i<<1)
    			for(int k=0;k<i;k++) {
    				int x=r[j+k],y=1ll*r[i+j+k]*(op==1?w:rw)[k*d]%mod;
    				r[j+k]=(x+y)%mod,r[i+j+k]=(x-y+mod)%mod;
    			}
    	if(op==-1) {
    		int inv=qpow(N,mod-2);
    		for(int i=0;i<N;i++) r[i]=1ll*r[i]*inv%mod;
    	}
    }
    
    int tmp1[maxn],tmp2[maxn];
    
    void get_inv(int *r,int *s,int len) {
    	if(len==1) return s[0]=qpow(r[0],mod-2),void();
    	get_inv(r,s,len>>1);
    	for(int i=0;i<len>>1;i++) tmp1[i]=s[i];
    	for(int i=len>>1;i<len;i++) tmp1[i]=0;
    	for(int i=0;i<len;i++) tmp2[i]=r[i];
    
    	for(bit=0,N=1;N<=len;N<<=1,bit++);
    	for(int i=1;i<N;i++) pos[i]=pos[i>>1]>>1|((i&1)<<(bit-1));
    	for(int i=len;i<N;i++) tmp1[i]=tmp2[i]=0;
    	ntt(tmp1,1),ntt(tmp2,1);
    	for(int i=0;i<N;i++) s[i]=((2ll*tmp1[i]%mod-1ll*tmp2[i]*tmp1[i]%mod*tmp1[i]%mod)%mod+mod)%mod;
    	ntt(s,-1);
    	for(int i=len;i<N;i++) s[i]=0;
    }
    
    int main() {
    	read(n);
    	for(mxn=1;mxn<=n<<1;mxn<<=1);
    	prepare();
    	fac[0]=ifac[0]=c[0]=1;
    	for(int i=1;i<=mxn;i++) fac[i]=1ll*fac[i-1]*i%mod;
    	ifac[mxn]=qpow(fac[mxn],mod-2);
    	for(int i=mxn-1;i;i--) ifac[i]=1ll*ifac[i+1]*(i+1)%mod;
    	for(int i=1;i<=n;i++) g[i]=qpow(2,(1ll*i*(i-1)/2)%(mod-1));
    	for(int i=1;i<=n;i++) c[i]=1ll*g[i]*ifac[i]%mod,b[i]=1ll*g[i]*ifac[i-1]%mod;
    	
    	get_inv(c,a,mxn>>1);
    	for(bit=0,N=1;N<mxn;N<<=1,bit++);
    	for(int i=1;i<N;i++) pos[i]=pos[i>>1]>>1|((i&1)<<(bit-1));
    	ntt(a,1),ntt(b,1);
    	for(int i=0;i<N;i++) a[i]=1ll*a[i]*b[i]%mod;
    	ntt(a,-1);
    	printf("%lld
    ",(1ll*a[n]*fac[n-1]%mod+mod)%mod);
    	return 0;
    }
    
  • 相关阅读:
    多说社交评论插件学习《一》
    《转》每天起床时,优秀创业者都会问自己这3个问题
    老赵面试题参考答案(二)《转》
    老赵面试题参考答案(一)《转》
    20个开源项目托管站点推荐
    .NET面试题(二)
    .NET面试题(一)
    Python笔记(28)-----继承
    pytorch实战(2)-----回归例子
    深度学习之入门Pytorch(1)------基础
  • 原文地址:https://www.cnblogs.com/hbyer/p/10555128.html
Copyright © 2020-2023  润新知