Description
有一天, Aoki给了Takahashi这样一个问题:
- 给定一颗有N个节点的树和一个整数K. 这些节点从1到N标号, 边被表示为整数对(ai,bi).
- 对于一个点集S, 我们定义f(S)表示一棵包含S中所有节点的最小子树的节点数量.(子树被定义为原树中的一个连通子图)
- 我们有(nk)种在整棵树中选K个节点的方案. 对于所有这些方案, 我们用S表示选择的节点组成的集合, 请你求出所有(nk)个集合的f(S)之和. 答案对924844033(质数)取模.
Takahashi觉得这个问题太傻, 因此他决定求出对于K=1,2,⋯N的所有答案.
Input
第一行一个整数 n ,接下来 n−1 行,每行两个整数 ai,bi 。
Output
N行, 第i行表示当K=i时的答案模924844033得到的余数.
Sample Input
sample input 1:
3
1 2
2 3
sample input 2:
4
1 2
1 3
1 4
sample input 3:
7
1 2
2 3
2 4
4 5
4 6
6 7
Sample Output
sample output 1:
3
7
3
sample output 2:
4
15
13
4
sample output 3:
7
67
150
179
122
45
7
HINT
样例 1 当K=2时答案如上图 。
数据满足:
- 2≤N≤2×105
- 1≤ai,bi≤N
- 给定的图是一颗树
大概有27分左右满足n≤2700。。?
思路
首先显然可以考虑每个点的贡献之后再容斥,就变成了对每个x求∑mk=1(ckx),其中m=2∗(n−1),ck是每条边两边的子树大小。
注意到ck≤n,所以把相同的ck合到一起之后,就变成了∑n k=1 ck(k/x)=1/x! ∑k ckk!/(k−x)!
发现是个卷积,直接NTT就行了。
代码
#include<bits/stdc++.h>
#define ll long long
#define N 800077
#define mod 924844033
#define G 5
#define unG 554906420
using namespace std;
int n;
struct edge{int v,nxt;}e[N<<1];
int hd[N],cnt;
inline void add(int u, int v){e[++cnt]=(edge){v,hd[u]}, hd[u]=cnt;}
int power(int x, int y)
{
int ret=1;
while(y)
{
if(y&1) ret=(ll)ret*x%mod;
x=(ll)x*x%mod;
y>>=1;
}
return ret;
}
int siz[N],num[N];
void dfs(int u, int fa){
siz[u]=1;
for(int i=hd[u]; i; i=e[i].nxt) if(e[i].v!=fa){
dfs(e[i].v,u);
siz[u]+=siz[e[i].v];
--num[siz[e[i].v]], --num[n-siz[e[i].v]];
}
}
int fac[N],unfac[N];
int a[N],b[N],c[N];
struct Poly
{
int n,bit,r[N];
void init(int x)
{
for(n=1, bit=0; n<=x; n<<=1, ++bit);
for(int i=1; i<n; ++i) r[i] = (r[i>>1]>>1) | ((i&1)<<(bit-1));
}
void dft(int *a, int f)
{
for(int i=0; i<n; ++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1; i<n; i<<=1)
{
int wn = power(f==1 ? G : unG, (mod-1)/(i<<1));
for(int j=0; j<n; j+=(i<<1)){
int w=1, x, y;
for(int k=0; k<i; ++k, w=(ll)w*wn%mod)
x=a[j+k], y=(ll)w*a[j+i+k]%mod,
a[j+k]=(x+y)%mod, a[j+i+k]=(x-y+mod)%mod;
}
}
if(f==-1)
{
int tmp=power(n,mod-2);
for(int i=0; i<n; ++i) a[i]=(ll)a[i]*tmp%mod;
}
}
}NTT;
int main()
{
scanf("%d",&n);
for(int i=1,u,v; i<n; ++i) scanf("%d%d",&u,&v),add(u,v),add(v,u);
fac[0]=1;
for(int i=1; i<=n; ++i) fac[i]=(ll)fac[i-1]*i%mod;
unfac[n]=power(fac[n],mod-2);
for(int i=n-1; i>=0; --i) unfac[i]=(ll)unfac[i+1]*(i+1)%mod;
dfs(1,0);
num[n]=n;
for(int i=0; i<=n; ++i)
b[i]=((ll)num[n-i]*fac[n-i]%mod+mod)%mod,
c[i]=unfac[i];
NTT.init(n*2+1), NTT.dft(b,1), NTT.dft(c,1);
for(int i=0; i<NTT.n; ++i) a[i]=(ll)b[i]*c[i]%mod;
NTT.dft(a,-1);
for(int i=1; i<=n; ++i) printf("%lld\n",(ll)a[n-i]*unfac[i]%mod);
}