• BZOJ3456 城市规划 【生成函数】【FFT】


    题目分析:

    容易想到生成函数的构造方法。

    令g(n)表示n个点的无向图个数,f(n)表示n个点的无向连通图的个数。式子是显然的。

    容易发现式子是卷积的形式,写出生成函数,然后多项式求逆后多项式乘法即可。

    代码:

      

    #include<bits/stdc++.h>
    using namespace std;
    
    int n;
    
    const int maxn = 800000;
    const int mod = 1004535809;
    const int gg = 3;
    
    int A[maxn],B[maxn],IB[maxn],B0[maxn],F[maxn];
    int fac[maxn/4],ord[maxn];
    
    int fast_pow(int now,long long pw){
        if(pw == 0) return 1;
        if(pw == 1) return now;
        int z = fast_pow(now,pw/2);
        z = (1ll*z*z)%mod;
        if(pw & 1) z = (1ll*z*now)%mod;
        return z;
    }
    
    void FFT(int *d,int len,int dr){
        for(int i=0;i<len;i++) if(ord[i] < i) swap(d[i],d[ord[i]]);
        for(int i=1;i<len;i<<=1){
        int wn = fast_pow(gg,(mod-1)/(i<<1));
        if(dr == -1) wn = fast_pow(wn,mod-2);
        for(int j=0;j<len;j+=(i<<1)){
            int w = 1;
            for(int k=0;k<i;k++,w=(1ll*w*wn)%mod){
            int x = d[j+k],y = (1ll*w*d[j+k+i])%mod;
            d[j+k] = (x+y)%mod; d[j+k+i] = (x-y)%mod;
            if(d[j+k+i] < 0) d[j+k+i]+=mod;
            }
        }
        }
        if(dr == -1){
        int iv = fast_pow(len,mod-2);
        for(int i=0;i<len;i++) d[i] = (1ll*d[i]*iv)%mod;
        }
    }
    
    void GetA(){
        for(int i=0;i<=n;i++)
        A[i] = (1ll*fast_pow(2,1ll*i*(i-1)/2)*fast_pow(fac[i-1],mod-2))%mod;
    }
    
    void GetB(){
        for(int i=0;i<=n;i++)
        B[i] = (1ll*fast_pow(2,1ll*i*(i-1)/2)*fast_pow(fac[i],mod-2))%mod;
    }
    
    void Inv(){
        IB[0] = fast_pow(B[0],mod-2);
        int res = 1;
        while(res < n+1) res=res<<1;
        for(int i=2,j=1;i<=res;i<<=1,j++){
        int bit = i*2,om = j+1;
        for(int k=0;k<i;k++) B0[k] = B[k];
        for(int k=0;k<bit;k++) ord[k]=(ord[k>>1]>>1)+((k&1)<<om-1);
        FFT(IB,bit,1);FFT(B0,bit,1);
        for(int k=0;k<bit;k++) B0[k]=(1ll*B0[k]*((1ll*IB[k]*IB[k])%mod))%mod;
        for(int k=0;k<bit;k++) IB[k] = (1ll*2*IB[k]-B0[k]+mod)%mod;
        FFT(IB,bit,-1);
        for(int k=i;k<2*i;k++) IB[k] = 0;
        }
        for(int i=n;i<=res;i++) IB[i] = 0;
    }
    
    void Multi(){
        int res = 1,len = 0;
        while(res < 2*n+1)res = res<<1,len++;
        for(int i=0;i<res;i++) ord[i]=(ord[i>>1]>>1)+((i&1)<<len-1);
        FFT(IB,res,1);FFT(A,res,1);
        for(int i=0;i<res;i++) F[i] = (1ll*A[i]*IB[i])%mod;
        FFT(F,res,-1);
    }
    
    void work(){fac[0] = 1;
        for(int i=1;i<=n;i++) fac[i] = (1ll*fac[i-1]*i)%mod;
        GetA();
        GetB();
        Inv();
        Multi();
        F[n] = (1ll*F[n]*fac[n-1])%mod;
        printf("%d",F[n]); 
    }
    
    int main(){
        scanf("%d",&n);
        work();
        return 0;
    }
  • 相关阅读:
    [Cocos2d-x]Cocos2d-x开发中C++调用Object-c
    [数据结构]基本概念
    [Cocos2d-x]Mac下运行HelloCpp For Android
    [Android] JDK , NDK , JNI
    [Cocos2d-x]坐标系
    [Android]mac下开发环境搭建
    [Cocos2d-x]博客推荐
    nyoj-506-洗澡
    nyoj-479-Coprimes
    nyoj-464-Cookies
  • 原文地址:https://www.cnblogs.com/Menhera/p/8985887.html
Copyright © 2020-2023  润新知