[AGC005F] Many Easy Problems
题意简述
给定一颗无根树,对于所有大小为 $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; }