[AGC005F] Many Easy Problems

link

题意简述

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

$n\leq 2\times 10^5$ 。

$solution:$

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

$$f_i=n\times\dbinom{n}{k}-\sum_{i=1}^n \dbinom{n-size_i}{k}+\sum_{x\in i} \dbinom{size_x}{k}\\=n\times \dbinom{n}{k}-\sum_{i=k}^n cnt_i\dbinom{i}{k}\\=n\times \dbinom{n}{k}-\dfrac{1}{k}\sum_{i=k}^n \dfrac{i!}{(i-k)}$$

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

$$f_i=n\times \dbinom{n}{k}-\sum_{i=k}^n a_i\times 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\n",(((a-b)%mod)+mod)%mod);
    }return 0;
}
View Code

 

posted @ 2019-07-14 20:06  siruiyang_sry  阅读(150)  评论(0编辑  收藏  举报