[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
原文地址:https://www.cnblogs.com/si-rui-yang/p/11185450.html