您的位置:首页 > 其它

[agc005f]Many Easy Problems

2017-10-31 10:52 288 查看

前言

居然有FFT题。

题目大意

给你一棵树,对于每个k求出在树上任选k个点形成虚树大小的和。

做法

假设这是有根树。

考虑一个点i对于一个k的贡献,考虑容斥。

Ckn−∑j是i儿子Cksize[j]−Ckn−size[i]

假设a[i]表示最终答案中Cki的系数,对于任何k来说a都是不变的。

然后答案ans[k]=∑ni=ka[i]∗Cki

ans[k]=1k!∗∑ni=ka[i]∗i!∗1(i−k)!

这显然可以卷积。

NTT即可。

#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn=200000+10,maxlen=maxn*4,mo=924844033,GG=5;
int size[maxn],h[maxn],go[maxn*2],nxt[maxn*2];
int w[maxlen],a[maxlen],b[maxlen],tt[maxlen],c[maxlen],rev[maxlen],fac[maxn],inv[maxn];
int i,j,k,l,t,n,m,tot,len,ans,ni;
db ce;
void add(int x,int y){
go[++tot]=y;
nxt[tot]=h[x];
h[x]=tot;
}
int qsm(int x,int y){
if (!y) return 1;
int t=qsm(x,y/2);
t=(ll)t*t%mo;
if (y%2) t=(ll)t*x%mo;
return t;
}
void dfs(int x,int y){
a
++;
int t=h[x];
size[x]=1;
while (t){
if (go[t]!=y){
dfs(go[t],x);
a[size[go[t]]]--;
size[x]+=size[go[t]];
}
t=nxt[t];
}
a[n-size[x]]--;
}
void prepare(){
w[0]=1;
w[1]=qsm(GG,(mo-1)/len);
fo(i,2,len) w[i]=(ll)w[i-1]*w[1]%mo;
fo(i,0,len-1){
int p=0;
for(int j=0,tp=i;j<ce;j++,tp/=2) p=(p<<1)+(tp%2);
rev[i]=p;
}
ni=qsm(len,mo-2);
}
void DFT(int *a,int sig){
int i;
fo(i,0,len-1) tt[rev[i]]=a[i];
for(int m=2;m<=len;m*=2){
int half=m/2,bei=len/m;
fo(i,0,half-1){
int wi=sig>0?w[i*bei]:w[len-i*bei];
for(int j=i;j<len;j+=m){
int u=tt[j],v=(ll)tt[j+half]*wi%mo;
tt[j]=(u+v)%mo;
tt[j+half]=(u-v)%mo;
}
}
}
if (sig==-1)
fo(i,0,len-1) tt[i]=(ll)tt[i]*ni%mo;
fo(i,0,len-1) a[i]=tt[i];
}
void NTT(){
DFT(a,1);DFT(b,1);
fo(i,0,len-1) a[i]=(ll)a[i]*b[i]%mo;
DFT(a,-1);
fo(i,0,len-1) c[i]=a[i];
}
int main(){
scanf("%d",&n);
fo(i,1,n-1){
scanf("%d%d",&j,&k);
add(j,k);add(k,j);
}
dfs(1,0);
fac[0]=1;
fo(i,1,n) fac[i]=(ll)fac[i-1]*i%mo;
inv
=qsm(fac
,mo-2);
fd(i,n-1,0) inv[i]=(ll)inv[i+1]*(i+1)%mo;
fo(i,0,n) a[i]=(ll)a[i]*fac[i]%mo;
fo(i,0,n) b[i]=inv[i];
reverse(b,b+n+1);
len=1;
while (len<=2*n) len*=2;
ce=log(len)/log(2);
prepare();
NTT();
fo(i,1,n){
ans=(ll)inv[i]*c[n+i]%mo;
(ans+=mo)%=mo;
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: