您的位置:首页 > 其它

AtCoder Grand Contest 005F - Many Easy Problems

2018-04-16 09:54 387 查看

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

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

现在$Ans_k=n\binom{n}{k}-\sum \binom{s(i,j)}{k}$,瓶颈在后面那坨。由于$s(i,j)$的取值只有$0~n$且只有$2(n-1)$个,因此可以dfs一次记$cnt_i=\sum_{s(j,k)=i}1$,有$\sum \binom{s(i,j)}{k}=\sum_{i=1}^n cnt_i\binom{i}{k}$。记$\sum \binom{s(i,j)}{k}=B_k$,因此$k!B_k=\sum_{i=1}^ncnt_i\frac{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
*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
=powmod(fac
,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\n",Ans[i]);
102     return 0;
103 }
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: