AtCoder Grand Contest 005F

$n leq 200000$的树,从树上选$k$个点的一个方案会对$Ans_k$产生大小为“最小的包括这$k$个点的连通块大小”的贡献。求每个$Ans_k$。膜924844033。

看每个点对$Ans_k$的贡献,那就是他在最小$k$连通块里的方案数。画画图可以发现,以他为根时,如果$k$个点都在他同一个儿子的子树里,那就是不包括这个点的,否则就是包括这个点的。“正难♂取反”,所以一个点的贡献就是$inom{n}{k}-sum inom{s(i,j)}{k}$,其中$s(i,j)$表示以$i$为根,子树$j$的大小。这样可以$n^2$。

现在$Ans_k=ninom{n}{k}-sum inom{s(i,j)}{k}$,瓶颈在后面那坨。由于$s(i,j)$的取值只有$0~n$且只有$2(n-1)$个,因此可以dfs一次记$cnt_i=sum_{s(j,k)=i}1$,有$sum inom{s(i,j)}{k}=sum_{i=1}^n cnt_iinom{i}{k}$。记$sum inom{s(i,j)}{k}=B_k$,因此$k!B_k=sum_{i=1}^ncnt_ifrac{i!}{(i-k)!}$,棒,一卷积。

924844033原根5。

  1 //#include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 //#include<time.h>
  5 //#include<complex>
  6 #include<algorithm>
  7 #include<stdlib.h>
  8 using namespace std;
  9 
 10 #define LL long long
 11 int qread()
 12 {
 13     char c; int s=0; while ((c=getchar())<'0' || c>'9');
 14     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s;
 15 }
 16 
 17 //Pay attention to '-' and LL of qread!!!!
 18 
 19 int n;
 20 #define maxn 531111
 21 const int mod=924844033,G=5; int rev[maxn];
 22 struct Edge{int to,next;}edge[maxn<<1]; int first[maxn],le=2;
 23 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
 24 void insert(int x,int y) {in(x,y); in(y,x);}
 25 
 26 int B[maxn],A[maxn],D[maxn],Ans[maxn],cnt[maxn],fac[maxn],inv[maxn];
 27 int C(int n,int m) {return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;}
 28 
 29 int powmod(int a,int b)
 30 {
 31     int ans=1;
 32     while (b) {if (b&1) ans=1ll*ans*a%mod; a=1ll*a*a%mod; b>>=1;}
 33     return ans;
 34 }
 35 
 36 void dft(int *a,int n,int type)
 37 {
 38     int wei=0; while ((1<<wei)!=n) wei++;
 39     for (int i=0;i<n;i++)
 40     {
 41         rev[i]=0;
 42         for (int j=0;j<wei;j++) rev[i]|=((i>>j)&1)<<(wei-j-1);
 43     }
 44     for (int i=0;i<n;i++) if (i<rev[i]) a[i]^=a[rev[i]]^=a[i]^=a[rev[i]];
 45     for (int i=1;i<n;i<<=1)
 46     {
 47         int t=powmod(G,(mod-1)/(i*2));
 48         if (type==-1) t=powmod(t,mod-2);
 49         for (int j=0,p=i<<1;j<n;j+=p)
 50         {
 51             int tmp=1;
 52             for (int k=0;k<i;k++,tmp=1ll*tmp*t%mod)
 53             {
 54                 int now=1ll*tmp*a[j+k+i]%mod;
 55                 a[j+k+i]=(a[j+k]+mod-now)%mod;
 56                 a[j+k]=(a[j+k]+now)%mod;
 57             }
 58         }
 59     }
 60     if (type==-1)
 61     {
 62         int ni=powmod(n,mod-2);
 63         for (int i=0;i<n;i++) a[i]=1ll*a[i]*ni%mod;
 64     }
 65 }
 66 
 67 void mul(int *a,int *b,int *c,int n)
 68 {
 69     dft(a,n,1); dft(b,n,1);
 70     for (int i=0;i<n;i++) c[i]=1ll*a[i]*b[i]%mod;
 71     dft(c,n,-1);
 72 }
 73 
 74 int size[maxn];
 75 void dfs(int x,int fa)
 76 {
 77     size[x]=1;
 78     for (int i=first[x];i;i=edge[i].next)
 79     {
 80         Edge &e=edge[i]; if (e.to==fa) continue;
 81         dfs(e.to,x); size[x]+=size[e.to];
 82         cnt[size[e.to]]++; cnt[n-size[e.to]]++;
 83     }
 84 }
 85 
 86 int main()
 87 {
 88     n=qread();
 89     for (int i=1,x,y;i<n;i++) {x=qread(); y=qread(); insert(x,y);}
 90     dfs(1,0);
 91     
 92     fac[0]=1; for (int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod;
 93     inv[n]=powmod(fac[n],mod-2); for (int i=n;i;i--) inv[i-1]=1ll*inv[i]*i%mod;
 94     for (int i=1;i<=n;i++) B[n-i+1]=1ll*cnt[i]*fac[i]%mod;
 95     for (int i=0;i<=n;i++) A[i]=inv[i];
 96     int mm=1; for (;mm<=(n+n);mm<<=1);
 97     mul(B,A,D,mm);
 98     for (int i=1;i<=n;i++) Ans[i]=1ll*inv[i]*D[n+1-i]%mod;
 99     
100     for (int i=1;i<=n;i++) Ans[i]=(1ll*n*C(n,i)%mod+mod-Ans[i])%mod;
101     for (int i=1;i<=n;i++) printf("%d
",Ans[i]);
102     return 0;
103 }
View Code
原文地址:https://www.cnblogs.com/Blue233333/p/8854201.html