zoukankan      html  css  js  c++  java
  • HDU 5279 分治NTT 图的计数

    思路:

    显然每个子图内都是森林

    去掉所有子图1和n都连通且每条大边都存在的情况

    直接DP上

    NTT优化一波

    注意前两项的值..

    //By SiriusRen
    #include <bits/stdc++.h>
    using namespace std;
    const int mod=998244353,N=262144;
    int cases,n,R[N],fac[N],inv[N],A[N],B[N],h[N],f[N],g[N],jy;
    int power(int x,int y){
        int r=1;
        while(y){
            if(y&1)r=1ll*x*r%mod;
            x=1ll*x*x%mod,y>>=1;
        }return r;
    }
    void NTT(int *a,int f,int m){
        int L=0,n;
        for(n=1;n<m;n<<=1)L++;
        for(int i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
        for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]);
        for(int l=1;l<n;l<<=1){
            int wn=power(3,((mod-1)/(l<<1)*f+(mod-1))%(mod-1));
            for(int j=0;j<n;j+=(l<<1)){
                int w=1;
                for(int k=0;k<l;k++,w=1ll*w*wn%mod){
                    int x=a[j+k],y=1ll*w*a[j+k+l]%mod;
                    a[j+k]=(x+y)%mod,a[j+k+l]=(x-y+mod)%mod;
                }
            }
        }
        if(f==-1){
            int ni=power(n,mod-2);
            for(int i=0;i<n;i++)a[i]=1ll*a[i]*ni%mod;
        }
    }
    void cdq(int l,int r){
        if(l==r){
            if(l==1)f[l]=1;
            else f[l]=(1ll*f[l]*fac[l-1]+1ll*h[l]*fac[l-1])%mod;
            return;
        }
        int mid=(l+r)>>1;
        cdq(l,mid);
        int len1=mid-l+1,len2=r-l+1,len=1;
        while(len<len1+len2)len<<=1;
        for(int i=0;i<len1;i++)A[i]=1ll*f[l+i]*inv[l+i]%mod;
        for(int i=len1;i<len;i++)A[i]=0;
        for(int i=0;i<len2;i++)B[i]=h[i];
        for(int i=len2;i<len;i++)B[i]=0;
        NTT(A,1,len),NTT(B,1,len);
        for(int i=0;i<len;i++)A[i]=1ll*A[i]*B[i]%mod;
        NTT(A,-1,len);
        for(int i=mid+1;i<=r;i++)f[i]=(f[i]+A[i-l])%mod;
        cdq(mid+1,r);
    }
    void init(){
        fac[0]=h[1]=1;
        for(int i=1;i<=100000;i++)fac[i]=1ll*fac[i-1]*i%mod;
        inv[100000]=power(fac[100000],mod-2);
        for(int i=99999;~i;i--)inv[i]=1ll*inv[i+1]*(i+1)%mod;
        for(int i=2;i<=100000;i++)h[i]=1ll*power(i,i-2)*inv[i-1]%mod;
        cdq(1,100000),f[0]=1;
        for(int i=0;i<262144;i++)A[i]=B[i]=0;
        for(int i=0;i<=100000;i++)A[i]=1ll*f[i]*inv[i]%mod;
        B[0]=B[1]=0;
        for(int i=2;i<=100000;i++)B[i]=1ll*h[i]*(i-1)%mod;
        NTT(A,1,262144),NTT(B,1,262144);
        for(int i=0;i<262144;i++)g[i]=1ll*A[i]*B[i]%mod; 
        NTT(g,-1,262144),g[1]=1;
        for(int i=2;i<=100000;i++)g[i]=1ll*g[i]*fac[i-2]%mod;
    }
    int main(){
        scanf("%d",&cases),init();
        while(cases--){
            scanf("%d",&n);int a1=1,a2=1;
            for(int i=1;i<=n;i++)scanf("%d",&jy),a1=1ll*a1*f[jy]%mod,a2=1ll*a2*g[jy]%mod;
            printf("%lld
    ",(1ll*a1*power(2,n)%mod-a2+mod)%mod);
        }
    }
  • 相关阅读:
    解决:信息中插入avi格式的视频时,提示“unsupported video format”
    java字节数组和16进制之间的转换
    16进制转换字节数组工具类
    如何在ubuntu 12.04 中安装经典的 GNOME桌面
    Ubuntu安装软件提示”需要安装不能信任的软件包”解决办法
    Ubuntu系统下运行Eclipse出现找不到jre的问题的解决方法
    ubuntu添加共享出错
    从scrapy使用经历说开来
    有趣的问题--12 coins problem
    一个奇怪的MySQL错误返回
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/7114891.html
Copyright © 2011-2022 走看看