zoukankan      html  css  js  c++  java
  • 【BZOJ3456】城市规划(生成函数,多项式运算)

    【BZOJ3456】城市规划(生成函数,多项式运算)

    题面

    (n)个点的无向连通图个数。

    (n<=130000)

    题解

    (n)个点的无向图的个数(g(n)=2^{C_n^2})。设(n)个点的无向连通图个数为(f(n))。有等式:

    [g(n)=sum_{i=1}^{n}C_{n-1}^{i-1}f(i)g(n-i) ]

    即考虑枚举(1)号点所在联通块的点。

    (g(n))带入式子

    [2^{C_n^2}=sum_{i=1}^{n}C_{n-1}^{i-1}f(i)2^{C_{n-i}^2} ]

    将组合数拆开后,两侧除掉只与(n)有关的((n-1)!)

    [frac{2^{C_n^2}}{(n-1)!}=sum_{i=1}^{n}frac{f(i)}{(i-1)!}frac{2^{C_{n-i}^2}}{(n-i)!} ]

    构造生成函数(F(x)=sum_{i=1}^{infty}frac{f(i)}{(i-1)!}x^i),(G(x)=sum_{i=0}^{infty}frac{g(i)}{i!}x^i),(C(x)=sum_{i=1}^{infty}frac{g(i)}{(i-1)!}x^i)

    然后有式子(C(x)=F(x)G(x))(F(x)=C(x)G^{-1}(x))

    多项式求逆即可,时间复杂度(O(nlogn))

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 333333
    const int MOD=1004535809;
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    int n,inv[MAX],jc[MAX],jv[MAX],p[MAX];
    int fpow(int a,int b)
    {
    	int s=1;
    	while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}
    	return s;
    }
    int r[MAX],W[MAX];
    void NTT(int *P,int len,int opt)
    {
    	int N,l=0;for(N=1;N<len;N<<=1)++l;
    	for(int i=1;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    	for(int i=1;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
    	for(int i=1;i<N;i<<=1)
    	{
    		int w=fpow(3,(MOD-1)/(i<<1));W[0]=1;
    		for(int k=1;k<i;++k)W[k]=1ll*W[k-1]*w%MOD;
    		for(int p=i<<1,j=0;j<N;j+=p)
    			for(int k=0;k<i;++k)
    			{
    				int X=P[j+k],Y=1ll*W[k]*P[i+j+k]%MOD;
    				P[j+k]=(X+Y)%MOD;P[i+j+k]=(X+MOD-Y)%MOD;
    			}
    	}
    	if(opt==-1)
    	{
    		reverse(&P[1],&P[N]);
    		for(int i=0,inv=fpow(N,MOD-2);i<N;++i)P[i]=1ll*P[i]*inv%MOD;
    	}
    }
    int A[MAX],B[MAX];
    void Inv(int *a,int *b,int len)
    {
    	if(len==1){b[0]=fpow(a[0],MOD-2);return;}
    	Inv(a,b,len>>1);
    	for(int i=0;i<len;++i)A[i]=a[i],B[i]=b[i];
    	NTT(A,len<<1,1);NTT(B,len<<1,1);
    	for(int i=0;i<(len<<1);++i)A[i]=1ll*A[i]*B[i]%MOD*B[i]%MOD;
    	NTT(A,len<<1,-1);
    	for(int i=0;i<len;++i)b[i]=((b[i]+b[i])%MOD+MOD-A[i])%MOD;
    	for(int i=0;i<(len<<1);++i)A[i]=B[i]=0;
    }
    int C[MAX],G[MAX],D[MAX],F[MAX];
    int main()
    {
    	n=read();
    	int N;for(N=1;N<=n;N<<=1);
    	inv[0]=jc[0]=inv[1]=jc[1]=jv[0]=jv[1]=1;
    	for(int i=2;i<=n;++i)
    	{
    		jc[i]=1ll*jc[i-1]*i%MOD;
    		inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
    		jv[i]=1ll*jv[i-1]*inv[i]%MOD;
    	}
    	p[0]=p[1]=1;
    	for(int i=2;i<=n;++i)p[i]=fpow(2,1ll*i*(i-1)/2%(MOD-1));
    	for(int i=0;i<=n;++i)G[i]=1ll*p[i]*jv[i]%MOD;
    	for(int i=1;i<=n;++i)C[i]=1ll*p[i]*jv[i-1]%MOD;
    	Inv(G,D,N);
    	NTT(D,N,1);NTT(C,N,1);
    	for(int i=0;i<N;++i)F[i]=1ll*D[i]*C[i]%MOD;
    	NTT(F,N,-1);
    	printf("%lld
    ",1ll*F[n]*jc[n-1]%MOD);
    	return 0;
    }
    
    
  • 相关阅读:
    ATS缓存数据结构
    Akamai CDN
    spring中的设计模式
    深入解析spring中用到的九种设计模式
    24种设计模式的通俗理解
    JDK中所包含的设计模式
    JDK源码中使用的设计模式
    算法-索引
    JAVA REENTRANTLOCK、SEMAPHORE 的实现与 AQS 框架
    扒一扒ReentrantLock以及AQS实现原理
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8798419.html
Copyright © 2011-2022 走看看