zoukankan      html  css  js  c++  java
  • BZOJ3456:城市规划——题解

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

    求出n个点的简单(无重边无自环)无向连通图数目

    模数很熟悉,先敲一个NTT。

    然后通过推导式子就做完啦!

    我觉得就算怎么讲也没有下面这一位好:http://blog.miskcoo.com/2015/05/bzoj-3456

    另外多项式求逆:http://blog.miskcoo.com/2015/05/polynomial-inverse

    至少我学到了:当你有个卷积知道答案,求卷积的一项时转换成生成函数再FFT一下就好了。

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<vector>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const ll P=1004535809;
    const int G=3;
    const int N=5e5+5;
    ll qpow(ll a,ll n,ll p){
        ll res=1;
        while(n){
            if(n&1)res=res*a%p;
            a=a*a%p;n>>=1;
        }
        return res;
    }
    void MTT(ll a[],int n,int on){
        for(int i=1,j=n>>1;i<n-1;i++){
            if(i<j)swap(a[i],a[j]);
            int k=n>>1;
            while(j>=k){j-=k;k>>=1;}
            if(j<k)j+=k;
        }
        for(int i=2;i<=n;i<<=1){
            ll res=qpow(G,(P-1)/i,P);
            for(int j=0;j<n;j+=i){
                ll w=1;
                for(int k=j;k<j+i/2;k++){
                    ll u=a[k],t=w*a[k+i/2]%P;
                    a[k]=(u+t)%P;
                    a[k+i/2]=(u-t+P)%P;
                    w=w*res%P;
                }
            }
        }
        if(on==-1){
            ll inv=qpow(n,P-2,P);
            a[0]=a[0]*inv%P;
            for(int i=1;i<=n/2;i++){
                a[i]=a[i]*inv%P;
                if(i!=n-i)a[n-i]=a[n-i]*inv%P;
                swap(a[i],a[n-i]);
            }
        }
    }
    ll t[N];
    void inv(int deg,ll a[],ll b[]){
        if(deg==1){
            b[0]=qpow(a[0],P-2,P);
            return;
        }
        inv((deg+1)>>1,a,b);
        int n=1;
        while(n<(deg<<1))n<<=1;
        for(int i=0;i<deg;i++)t[i]=a[i];
        for(int i=deg;i<n;i++)t[i]=0;
        MTT(t,n,1);MTT(b,n,1);
        for(int i=0;i<n;i++)
            b[i]=b[i]*(2-b[i]*t[i]%P+P)%P;
        MTT(b,n,-1);
        for(int i=deg;i<n;i++)b[i]=0;
    }
    int n;
    ll f[N],g[N],tmp[N],c[N],jc[N],C[N][3];
    inline void init(){
        jc[0]=jc[1]=1;C[0][2];
        for(int i=2;i<=n;i++)jc[i]=jc[i-1]*i%P;
        for(int i=1;i<=n;i++)C[i][2]=C[i-1][2]+i-1;
    }
    int main(){
        scanf("%d",&n);init();
        for(int i=0;i<=n;i++){
            g[i]=qpow(2,C[i][2],P)*qpow(jc[i],P-2,P)%P;
            if(i)c[i]=qpow(2,C[i][2],P)*qpow(jc[i-1],P-2,P)%P;
        }
        int nn=1;
        while(nn<=n)nn<<=1;
        
        inv(nn,g,tmp);memcpy(g,tmp,sizeof(tmp));
        
        MTT(g,nn,1);MTT(c,nn,1);
        for(int i=0;i<nn;i++)f[i]=g[i]*c[i]%P;
        MTT(f,nn,-1);
        
        f[n]=f[n]*jc[n-1]%P;
        printf("%lld
    ",f[n]);
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    第5次作业
    第六次作业
    第五次作业
    软件需求最佳实践阅读笔记05
    软件需求最佳实践阅读笔记04
    构建民航知识图谱
    软件需求最佳实践阅读笔记03
    软件需求最佳实践阅读笔记02
    软件需求最佳实践阅读笔记01
    程序员的自我修养阅读笔记03
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9005048.html
Copyright © 2011-2022 走看看