CF 954H Path Counting

H. Path Counting
time limit per test
5 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given a rooted tree. Let's denote d(x) as depth of node x: depth of the root is 1, depth of any other node x is d(y) + 1, where yis a parent of x.

The tree has the following property: every node x with d(x) = i has exactly ai children. Maximum possible depth of a node is n, and an = 0.

We define fk as the number of unordered pairs of vertices in the tree such that the number of edges on the simple path between them is equal to k.

Calculate fk modulo 109 + 7 for every 1 ≤ k ≤ 2n - 2.

Input

The first line of input contains an integer n (2  ≤  n  ≤  5 000) — the maximum depth of a node.

The second line of input contains n - 1 integers a1,  a2,  ...,  an - 1 (2 ≤  ai  ≤ 109), where ai is the number of children of every node xsuch that d(x) = i. Since an = 0, it is not given in the input.

Output

Print 2n - 2 numbers. The k-th of these numbers must be equal to fk modulo 109 + 7.

Examples
input
Copy
4
2 2 2
output
Copy
14 19 20 20 16 16 
input
Copy
3
2 3
output
Copy
8 13 6 9 
Note

This the tree from the first sample:

 

【题意】

给出一棵深度为n的树,其中每个深度为i的节点都有a[i]个儿子。问对于每个k,有多少条简单路径满足其长度恰好为k

n<=5000

 

【分析】

考虑枚举路径的端点。

d[i,j]表示从某个深度为i的节点开始,只往下走且长度为j的路径条数。那么d[i,j]显然等于i的子树中深度为i+j的点数。

u[i,j]表示从某个深度为i的节点开始,第一步必须往上走,且路径长度为j的方案。

有两种转移,一种是走到父亲后继续往上,贡献就等于u[i-1,j-1]。另一种转移是走到父亲后就开始往下走,贡献就等于u[i,j-2]*(a[i-1]-1)

综上,f[i][j]= f[i+1][j-1]*a[i]+

f[i-1][j-1]+

f[i][j-2]*(a[i-1]-1);

 

【代码】

#include<cstdio>
#include<cstring>
#include<iostream>
#define debug(x) cerr<<#x<<" "<<x<<'\n';
using namespace std;
typedef long long ll;
const int N=5005;
const ll mod=1e9+7;
const ll rev=5e8+4;
int n,a[N],p[N],f[N][N<<1],ans[N<<1];
int main(){
	scanf("%d",&n);p[0]=1;
	for(int i=1;i<n;i++) scanf("%d",&a[i]),p[i]=(ll)p[i-1]*a[i]%mod;
	for(int i=n;i;i--){
		f[i][0]=1;
		for(int j=1;j<=n-i;j++){
			f[i][j]=(ll)f[i+1][j-1]*a[i]%mod;
			ans[j]=((ll)ans[j]+(ll)f[i][j]*p[i-1])%mod;
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=2*n-2;j>=1;j--){
			f[i][j]=f[i-1][j-1];
			if(i>1&&j>1&&j-2<n&&j<=i+n-2) f[i][j]=((ll)f[i][j]+(ll)f[i][j-2]*(a[i-1]-1))%mod;
			ans[j]=((ll)ans[j]+(ll)f[i][j]*p[i-1])%mod;
		}
	}
	for(int i=1;i<=2*n-2;i++) printf("%I64d ",(ll)ans[i]*rev%mod);
	return 0;
} 
posted @ 2019-02-23 20:46  神犇(shenben)  阅读(300)  评论(0编辑  收藏  举报