• [AGC005F] Many Easy Problems


    link

    题意简述

    给定一颗无根树,对于所有大小为 $i$ 的点集,求出能够包含它的所有联通块之和,定义为 $f_i$ ,答案对 $924844033$ 取模。

    $nleq 2 imes 10^5$ 。

    $solution:$

    考虑每个点在点集中起到的贡献,可以得到

    $$f_i=n imesdbinom{n}{k}-sum_{i=1}^n dbinom{n-size_i}{k}+sum_{xin i} dbinom{size_x}{k}\=n imes dbinom{n}{k}-sum_{i=k}^n cnt_idbinom{i}{k}\=n imes dbinom{n}{k}-dfrac{1}{k}sum_{i=k}^n dfrac{i!}{(i-k)}$$

    设 $a_i=cnt_i imes i!,b_i=(n-i)!$ 。

    $$f_i=n imes dbinom{n}{k}-sum_{i=k}^n a_i imes b_{n-i+k}$$

    直接 $NTT$ 即可。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define int long long
    #define mod 924844033
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    const int MAXN=800001;
    int n,inv[MAXN],head[MAXN],fac[MAXN],infac[MAXN],Cnt,cnt[MAXN],siz[MAXN];
    int C(int n,int m){return (((fac[n]*infac[m])%mod)*infac[n-m])%mod;}
    struct node{
        int u,v,nex;
    }x[MAXN<<1];
    void add(int u,int v){
        x[Cnt].u=u,x[Cnt].v=v,x[Cnt].nex=head[u],head[u]=Cnt++;
    }
    int ksm(int a,int b){
        int ans=1;
        while(b){
            if(b&1) ans*=a,ans%=mod;
            a*=a,a%=mod;
            b>>=1;
        }return ans;
    }
    void dfs(int u,int fath){
        siz[u]=1;
        for(int i=head[u];i!=-1;i=x[i].nex){
            if(x[i].v==fath) continue;
            dfs(x[i].v,u);
            siz[u]+=siz[x[i].v];
            cnt[siz[x[i].v]]++;
        }
        cnt[n-siz[u]]++;
        return;
    }
    int N,M,flip[MAXN],f[MAXN],g[MAXN];
    void NTT(int *f,int opt){
        for(int i=0;i<N;i++) if(i<flip[i]) swap(f[i],f[flip[i]]);
        for(int p=2;p<=N;p<<=1){
            int len=p>>1,buf=ksm(5,(mod-1)/p);
            if(opt==-1) buf=ksm(buf,mod-2);
            for(int be=0;be<N;be+=p){
                int tmp=1;
                for(int l=be;l<be+len;l++){
                    int t=f[l+len]*tmp;t%=mod;
                    f[l+len]=(f[l]-t+mod)%mod,f[l]=(f[l]+t)%mod;
                    tmp*=buf,tmp%=mod;
                }
            }
        }
        if(opt==-1){
            int inv=ksm(N,mod-2);
            for(int i=0;i<N;i++) f[i]*=inv,f[i]%=mod;
        }return;
    }
    signed main(){
    //    freopen("6.in","r",stdin);
        memset(head,-1,sizeof(head));
        inv[1]=1;for(int i=2;i<=200000;i++) inv[i]=((mod-mod/i)*inv[mod%i])%mod;
        fac[0]=1;for(int i=1;i<=200000;i++) fac[i]=(fac[i-1]*i)%mod;
        infac[0]=1;for(int i=1;i<=200000;i++) infac[i]=(infac[i-1]*inv[i])%mod;
        n=read();
        for(int i=1;i<n;i++){
            int u=read(),v=read();
            add(u,v),add(v,u);
        }
        dfs(1,0);
        N=n,M=n;
        for(int i=0;i<=N;i++) f[i]=(cnt[i]*fac[i])%mod;
        for(int i=0;i<=M;i++) g[i]=infac[n-i];
        M+=N;
        for(N=1;N<=M;N<<=1);
        for(int i=0;i<N;i++) flip[i]=((flip[i>>1]>>1)|(i&1?N>>1:0));
        NTT(f,1),NTT(g,1);
        for(int i=0;i<N;i++) f[i]*=g[i],f[i]%=mod;
        NTT(f,-1);
        for(int i=1;i<=n;i++){
            int a=(n*C(n,i))%mod,b=(infac[i]*f[n+i])%mod;
            printf("%lld
    ",(((a-b)%mod)+mod)%mod);
        }return 0;
    }
    View Code
  • 相关阅读:
    1. 机器学习概述
    第十五次作业:语法制导的语义翻译
    第十四次作业:算符优先分析
    第十三次作业:自下而上语法分析
    第十二次作业:实验二 递归下降语法分析
    第十一次作业:LL(1)文法的判断,递归下降分析程序
    第十次作业:消除左递归
    20145225 《信息安全系统设计基础》第11周学习总结
    20145225 《信息安全系统设计基础》学习与补救一:代码驱动的程序设计学习
    20145225 《信息安全系统设计基础》第10周学习总结
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/11185450.html
Copyright © 2020-2023  润新知