当前位置: 代码迷 >> 综合 >> Atcoder 005 Editorial F - Many Easy Problems
  详细解决方案

Atcoder 005 Editorial F - Many Easy Problems

热度:112   发布时间:2023-10-29 06:25:30.0

前言

省选GG之后成为文化课选手。。
文化课都补不完的说
然后全部训练时间,都拿去补文化课了。。
于是今天中午终于做了一道题。。

题意

给你一棵树
然后对于所有的k
答案是你在n里面选择k个点,他的代价就是最少要选多少个点,他可以包含这个联通块
CknCnk种方案的代价和

题解

这题看起来不是很好做。。
然后我们考虑每一个点对答案的贡献
这个也不好做
那么我们就想能不能减去不合法的
那么对于一个点,他对kk的贡献就是
C n k ?
CknCnk提出来,就是要求有后面这个的总和
有什么是不合法的呢?
就是全的点,都在删除他时候,剩余树的某一个联通块里面
这个的话,就是Ckai∑Caik
考虑展开这个东西
Ckai=(ai)!k!(ai?k)!Caik=(ai)!k!(ai?k)!
然后k!k!可以提出来,那么剩下的就是一个卷积的形式来做了
然后我们由于要把所有点一起算,所以上面要乘上一个系数p[ai]p[ai]
表示联通块大小为aiai的有多少个
然后这题就做完了
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;
}
  相关解决方案