• 洛谷 P4841 城市规划 解题报告


    P4841 城市规划

    题意

    n个有标号点的简单(无重边无自环)无向连通图数目.

    输入输出格式

    输入格式:

    仅一行一个整数(n(le 130000))

    输出格式:

    仅一行一个整数, 为方案数 (mod 1004535809).


    (g_i)表示(i)个点的图的数目,(f_i)表示(i)个点联通图的个数

    [g_n=f_n+sum_{i=1}^{n-1}f_iinom{n-1}{i-1}g^{n-i} ]

    意义是联通图+非联通图,关于非联通图的方案,枚举1号点所在联通块然后剩下的随意构图,不连通。

    显然有(g_n=2^{inom{n}{2}}),化简一波式子

    [egin{aligned} 2^{inom{n}{2}}&=sum_{i=1}^nf_iinom{n-1}{i-1}2^{inom{n-i}{2}}\ frac{2^{inom{n}{2}}}{(n-1)!}&=sum_{i=1}^nfrac{f_i}{(i-1)!}frac{2^{inom{n-i}{2}}}{(n-i)!} end{aligned} ]

    然后令

    [F(i)=frac{f_i}{(i-1)!},G(i)=frac{2^{inom{i}{2}}}{(i-1)!},H(i)=frac{2^{inom{i}{2}}}{i!} ]

    显然有

    [G=F*H ]

    (H)求个逆就可以了。

    一些关于意义的边界问题可以试试,反正不是0就是1..

    调这个题的时候因为把指数给膜了,挂了20年...


    Code:

    #include <cstdio>
    #include <algorithm>
    const int mod=1004535809,Gi=334845270;
    const int N=(1<<20)+10;
    #define mul(a,b) (1ll*(a)*(b)%mod)
    #define add(a,b) ((a+b)%mod)
    int fac[N],inv[N],A[N],B[N],t[2][N],G[N],H[N],turn[N],n,len,L;
    int qp(int d,int k){int f=1;while(k){if(k&1)f=mul(f,d);d=mul(d,d),k>>=1;}return f;}
    void NTT(int *a,int typ)
    {
        for(int i=1;i<len;i++) if(i<turn[i]) std::swap(a[i],a[turn[i]]);
        for(int le=1;le<len;le<<=1)
        {
            int wn=qp(typ?3:Gi,(mod-1)/(le<<1));
            for(int p=0;p<len;p+=le<<1)
            {
                int w=1;
                for(int i=p;i<p+le;i++,w=mul(w,wn))
                {
                    int tx=a[i],ty=mul(w,a[i+le]);
                    a[i]=add(tx,ty);
                    a[i+le]=add(tx,mod-ty);
                }
            }
        }
        if(!typ)
        {
            int inv=qp(len,mod-2);
            for(int i=0;i<len;i++) a[i]=mul(a[i],inv);
        }
    }
    void polymul(int *a,int *b)
    {
        for(int i=0;i<len;i++) A[i]=B[i]=0;
        for(int i=0;i<len>>1;i++) A[i]=a[i],B[i]=b[i];
        NTT(A,1),NTT(B,1);
        for(int i=0;i<len;i++) A[i]=mul(A[i],B[i]);
        NTT(A,0);
        for(int i=0;i<len;i++) a[i]=A[i];
    }
    void init()
    {
        for(int i=1;i<len;i++) turn[i]=turn[i>>1]>>1|(i&1)<<L;
    }
    void polyinv(int *a,int n)
    {
        int cur=0;t[cur][0]=qp(a[0],mod-2);
        len=1,L=-1;
        while(len<=n<<2)
        {
            len<<=1,++L,cur^=1,init();
            for(int i=0;i<len>>1;i++) t[cur][i]=add(t[cur^1][i],t[cur^1][i]);
            polymul(t[cur^1],t[cur^1]);
            polymul(t[cur^1],a);
            for(int i=0;i<len;i++) t[cur][i]=add(t[cur][i],mod-t[cur^1][i]);
        }
        for(int i=0;i<=n;i++) a[i]=t[cur][i];
    }
    int main()
    {
        scanf("%d",&n);
        fac[0]=1;for(int i=1;i<=n;i++) fac[i]=mul(fac[i-1],i);
        inv[n]=qp(fac[n],mod-2);
        for(int i=n-1;~i;i--) inv[i]=mul(inv[i+1],i+1);
        for(int i=1;i<=n;i++) G[i]=mul(qp(2,1ll*i*(i-1)/2%(mod-1)),inv[i-1]);
        for(int i=0;i<=n;i++) H[i]=mul(qp(2,1ll*i*(i-1)/2%(mod-1)),inv[i]);//这个mod-1调了本菜鸡20years
        polyinv(H,n);
        polymul(G,H);
        printf("%d
    ",mul(G[n],fac[n-1]));
        return 0;
    }
    

    2018.12.26

  • 相关阅读:
    css实现文字渐变
    mySql中Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggre的问题
    mysql不等于判断时,空值过滤问题
    SpringBoot中maven打包,启动报没有主清单属性
    MySQL插入数据时报错Cause: java.sql.SQLException: #HY000的解决方法
    SpringCloud中Feign服务调用请求方式及参数总结
    linux查看占用端口号的程序及pid
    Ant Design Pro 改变默认启动端口号
    启动jar包并生成日志的linux脚本
    JavaWeb中验证码校验的功能实现
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10180329.html
Copyright © 2020-2023  润新知