zoukankan      html  css  js  c++  java
  • AT2064 [AGC005F] Many Easy Problems 容斥+NTT

    题意:令 $f(i)$ 表示对于 $inom{n}{i}$ 种包含 $i$ 个点的最小连通块的总节点个数和.

    面对个数和/价值和且点和点之间没有限制条件的问题时可以考虑单独处理每个点的贡献.    

    考虑点 $j$ 对 $f(i)$ 的贡献.  

    那么 $j$ 对 $f(i)$ 有贡献时分两种情况.   

    1. $j$ 是 $i$ 个点中的一个.

    2. $j$ 不是 $i$ 个点中的一个,但是 $j$ 被这个连通块所包含,那么就意味着至少 $j$ 的两个儿子中有 $i$ 集合中的点.      

    对于情况 1,方案数为 $inom{n-1}{i-1}.$  

    对于情况 2,方案数为 $inom{n-1}{i}-sum_{v subseteq son[j] } inom{son[v]}{i}.$    

    两种情况总和为:$inom{n}{i}-sum_{v subseteq son[j] } inom{son[v]}{i}$ 

    那么对于所有点加和,得 $f(i)=n inom{n}{i}- sum_{j=i}^{n} inom{j}{i} num(j).$   

    $Rightarrow f(i)=n inom{n}{i} - i!sum_{j=i}^{n} frac{j!num(j)}{(j-i)!}.$  

    前面的是常数,但后后面的式子差是定值,所以将系数翻转做一遍 NTT 即可.    

    #include <cstdio>  
    #include <cstring> 
    #include <cmath> 
    #include <vector>  
    #include <algorithm>      
    #define ll long long   
    #define N 1000003 
    #define MAX 200005       
    #define mod 924844033
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;  
    int n,edges; 
    int hd[N],to[N],nex[N],bu[N],fac[N],inv[N],t[N],g[N],size[N],Ans[N];   
    void add(int u,int v) 
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;    
    }
    int qpow(int x,int y) 
    { 
        int tmp=1; 
        for(;y;y>>=1,x=(ll)x*x%mod) 
            if(y&1) tmp=(ll)tmp*x%mod; 
        return tmp;   
    }
    int INV(int x) { return qpow(x,mod-2); }      
    void NTT(int *a,int len,int flag) 
    {
        int i,j,k,mid;     
        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(mid=1;mid<len;mid<<=1) 
        {
            int wn=qpow(5,(mod-1)/(mid<<1));     
            if(flag==-1) wn=INV(wn);      
            for(i=0;i<len;i+=mid<<1) 
            { 
                int w=1;      
                for(j=0;j<mid;++j) 
                {
                    int x=a[i+j],y=(ll)w*a[i+j+mid]%mod;         
                    a[i+j]=(ll)(x+y)%mod;    
                    a[i+j+mid]=(ll)(x-y+mod)%mod;    
                    w=(ll)w*wn%mod;    
                }
            }
        }
        if(flag==-1) 
        {
            int in=INV(len); 
            for(i=0;i<len;++i) a[i]=(ll)a[i]*in%mod;    
        }
    } 
    int C(int x,int y) 
    {
        if(x<y||x<0||y<0) return 0;   
        return (ll)fac[x]*inv[y]%mod*inv[x-y]%mod;    
    }
    void init() 
    {
        int i,j;     
        fac[0]=inv[0]=1;     
        for(i=1;i<MAX;++i) fac[i]=(ll)fac[i-1]*i%mod,inv[i]=INV(fac[i]);       
    }
    void dfs(int u,int ff) 
    {
        size[u]=1; 
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i]; 
            if(v==ff) continue;    
            dfs(v,u); 
            size[u]+=size[v];    
            bu[size[v]]++;   
        }  
        bu[n-size[u]]++;     
    }
    int main() 
    {     
        // setIO("input");   
        int i,j;    
        init();           
        scanf("%d",&n);   
        for(i=1;i<n;++i) 
        {
            int x,y;  
            scanf("%d%d",&x,&y),add(x,y),add(y,x);  
        }      
        dfs(1,0);  
        int ans=0;         
        for(i=0;i<=n;++i) g[i]=(ll)bu[i]*fac[i]%mod,t[n-i]=inv[i];          
        int lim=1;   
        while(lim<=2*n) lim<<=1;   
        NTT(g,lim,1),NTT(t,lim,1); 
        for(i=0;i<lim;++i) g[i]=(ll)g[i]*t[i]%mod;   
        NTT(g,lim,-1);      
        for(i=0;i<=n;++i)  Ans[i]=(ll)g[i+n]*inv[i]%mod;       
        for(i=1;i<=n;++i) 
        {
            int tmp=(ll)n*C(n,i)%mod;      
            printf("%d
    ",(ll)(tmp-Ans[i]+mod)%mod);   
        }        
        return 0;   
    }
    

      

  • 相关阅读:
    使用Python创建TCP代理之工业时代造轮子
    CVE-2020-0796 SMB远程代码执行漏洞(分析、验证及加固)
    Oracle 找到引起账户锁定的IP
    【OGG 故障处理】OGG-01031
    【OGG 故障处理】OGG-01028
    【OGG 故障处理】 丢失归档恢复
    19C imp 导入合并表空间
    CentOS 7 配置VNCServer
    ORA-3136 问题处理
    HugePages概述--翻译自19C文档
  • 原文地址:https://www.cnblogs.com/guangheli/p/12302623.html
Copyright © 2011-2022 走看看