前言
省选GG之后成为文化课选手。。
文化课都补不完的说
然后全部训练时间,都拿去补文化课了。。
于是今天中午终于做了一道题。。
题意
给你一棵树
然后对于所有的k
答案是你在n里面选择k个点,他的代价就是最少要选多少个点,他可以包含这个联通块
求
Ckn
C
n
k
种方案的代价和
题解
这题看起来不是很好做。。
然后我们考虑每一个点对答案的贡献
这个也不好做
那么我们就想能不能减去不合法的
那么对于一个点,他对
k
k
的贡献就是
把
Ckn
C
n
k
提出来,就是要求有后面这个的总和
有什么是不合法的呢?
就是全的点,都在删除他时候,剩余树的某一个联通块里面
这个的话,就是
∑Ckai
∑
C
a
i
k
考虑展开这个东西
Ckai=(ai)!k!(ai−k)!
C
a
i
k
=
(
a
i
)
!
k
!
(
a
i
−
k
)
!
然后
k!
k
!
可以提出来,那么剩下的就是一个卷积的形式来做了
然后我们由于要把所有点一起算,所以上面要乘上一个系数
p[ai]
p
[
a
i
]
表示联通块大小为
ai
a
i
的有多少个
然后这题就做完了
CODE:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const LL MOD=924844033;
const LL g=5;
const LL gi=554906420;
const LL N=200005*8;
struct qq
{
LL x,y,last;
}e[N*2];LL num,last[N];
LL n;
LL pow (LL x,LL y)
{
if (y==1) return x;
LL lalal=pow(x,y>>1);
lalal=lalal*lalal%MOD;
if (y&1) lalal=lalal*x%MOD;
return lalal;
}
void init (LL x,LL y)
{
num++;
e[num].x=x;e[num].y=y;
e[num].last=last[x];
last[x]=num;
}
LL tot[N];
LL a[N],b[N];
void dfs (LL x,LL fa)
{
tot[x]=1;
for (LL u=last[x];u!=-1;u=e[u].last)
{
LL y=e[u].y;
if (y==fa) continue;
dfs(y,x);
tot[x]+=tot[y];
}
if (fa!=0) {a[tot[x]]++;a[n-tot[x]]++;}
}
LL JC[N],inv[N];
LL bin[N];
void ntt (LL *a,LL n,LL o)
{
for (LL u=0;u<n;u++) bin[u]=(bin[u>>1]>>1)|((u&1)*(n>>1));
for (LL u=0;u<n;u++)
if (u<bin[u])
swap(a[u],a[bin[u]]);
for (LL u=1;u<n;u<<=1)
{
LL w,t,wn=pow(o==1?g:gi,(MOD-1)/(u<<1));
for (LL i=0;i<n;i=i+(u<<1))
{
w=1;
for (LL j=0;j<u;j++)
{
t=w*a[u+i+j]%MOD;
a[u+i+j]=(a[i+j]-t+MOD)%MOD;
a[i+j]=(a[i+j]+t)%MOD;
w=w*wn%MOD;
}
}
}
if (o==-1)
{
LL Inv=pow(n,MOD-2);for (LL u=0;u<n;u++) a[u]=a[u]*Inv%MOD;
}
}
int main()
{
//printf("%lld\n",pow(g,MOD-2));
num=0;memset(last,-1,sizeof(last));
scanf("%lld",&n);
for (LL u=1;u<n;u++)
{
LL x,y;
scanf("%lld%lld",&x,&y);
init(x,y);init(y,x);
}
dfs(1,0);
JC[0]=1;for (LL u=1;u<=n;u++) JC[u]=JC[u-1]*u%MOD;
inv[n]=pow(JC[n],MOD-2);for (LL u=n-1;u>=0;u--) inv[u]=inv[u+1]*(u+1)%MOD;
for (LL u=1;u<=n;u++) a[u]=a[u]*JC[u]%MOD;
for (LL u=0;u<=n;u++) b[u]=inv[n-u];
LL now=1;while (now<=n) now<<=1;now<<=1;
ntt(a,now,1);ntt(b,now,1);
for (LL u=0;u<now;u++) a[u]=a[u]*b[u]%MOD;
ntt(a,now,-1);
for (LL u=1;u<=n;u++)
{
now=JC[n]*inv[u]%MOD*inv[n-u]%MOD*n%MOD;
now=(now-a[n+u]*inv[u]%MOD+MOD)%MOD;
printf("%lld\n",now);
}
return 0;
}