• BZOJ3456: 城市规划


    BZOJ3456: 城市规划

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

    分析:

    • (f[n])表示(n)个点的答案, (g[n])表示总方案数。
    • 枚举和(1)连通的点的个数, (f[n]=g[n]-sumlimits_{i=1}^{n-1}inom{n-1}{i-1}f(i)g(n-i))
    • 然后把式子划开就是一个多项式求逆了

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define mod 1004535809
    #define N 400050
    typedef long long ll;
    int qp(int x,ll y) {
        int re=1; for(;y;y>>=1,x=ll(x)*x%mod) if(y&1) re=ll(re)*x%mod; return re;
    }
    #define INV(x) (qp(x,mod-2))
    void ntt(int *a,int len,int flg) {
        int i,j,k,t,w,wn,tmp;
        for(i=k=0;i<len;i++) {
            if(i>k) swap(a[i],a[k]);
            for(j=len>>1;(k^=j)<j;j>>=1) ;
        }
        for(k=2;k<=len;k<<=1) {
            t=k>>1;
            wn=qp(3,(mod-1)/k);
            if(flg==-1) wn=INV(wn);
            for(i=0;i<len;i+=k) {
                w=1;
                for(j=i;j<i+t;j++) {
                    tmp=ll(a[j+t])*w%mod;
                    a[j+t]=(a[j]-tmp)%mod;
                    a[j]=(a[j]+tmp)%mod;
                    w=ll(w)*wn%mod;
                }
            }
        }
        if(flg==-1) {
            t=INV(len);
            for(i=0;i<len;i++) a[i]=ll(a[i])*t%mod;
        }
    }
    int A[N],B[N],F[N],G[N],H[N],fac[N],inv[N],n,g[N];
    void get_inv(int *a,int *b,int len) {
        if(len==1) {
            b[0]=INV(a[0]); return ;
        }
        get_inv(a,b,len>>1);
        int t=len<<1,i;
        for(i=0;i<len;i++) A[i]=a[i],B[i]=b[i];
        ntt(A,t,1), ntt(B,t,1);
        for(i=0;i<t;i++) B[i]=(2-ll(A[i])*B[i])%mod*B[i]%mod;
        ntt(B,t,-1);
        for(i=0;i<len;i++) b[i]=B[i];
    }
    int main() {
        scanf("%d",&n);
        int i;
        for(fac[0]=i=1;i<=n;i++) fac[i]=ll(fac[i-1])*i%mod;
        for(i=1;i<=n;i++) {
            g[i]=qp(2,ll(i)*(i-1)/2);
        }
        inv[n]=INV(fac[n]);
        for(i=n-1;i>=0;i--) inv[i]=ll(inv[i+1])*(i+1)%mod;
        H[0]=1;
        for(i=1;i<=n;i++) {
            H[i]=ll(g[i])*inv[i]%mod;
            G[i]=ll(g[i])*inv[i-1]%mod;
        }
        int len=1;
        while(len<=n) len<<=1;
        get_inv(H,F,len);
        len<<=1;
        ntt(F,len,1), ntt(G,len,1);
        for(i=0;i<len;i++) F[i]=ll(F[i])*G[i]%mod;
        ntt(F,len,-1);
        printf("%lld
    ",(ll(F[n])*fac[n-1]%mod+mod)%mod);
    }
    
  • 相关阅读:
    JavaScript判断移动端及pc端访问不同的网站
    详情点击文字展开,再点击隐藏
    让IE6/IE7/IE8浏览器支持CSS3属性
    随机输入两位数,并将其交换位置输出
    100-999的水仙花数
    C++读取文件
    求n项阶乘之和并求出和的后六位
    n的阶乘
    3*n+1问题
    完全平方数的判断
  • 原文地址:https://www.cnblogs.com/suika/p/10017388.html
Copyright © 2020-2023  润新知