Path Counting (Codeforces 954H)
Tags: DP, combinatorics

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 y is 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 x such 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.

Note: This the tree from the first sample:   

Sample Inputs:
4
2 2 2

3
2 3

Sample Outputs:
14 19 20 20 16 16

8 13 6 9

Solution (Python):
import sys, os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
n = int(input())
a = list(map(int, input().split()))
mod = pow(10, 9) + 7
ans = [0] * (2 * n - 2)
b = list(a)
for i in range(1, n - 1):
    b[i] *= b[i - 1]
    b[i] %= mod
s = 0
for i in range(n - 2, -1, -1):
    s += b[i]
    s %= mod
    ans[i] = s
dp = [0] * (2 * n - 2)
for i in range(n - 1):
    bi = b[i]
    for j in range(i, n - 1):
        bj = 2 * b[j] % mod if i ^ j else b[j]
        dp[i + j + 1] += bi * bj % mod
        dp[i + j + 1] %= mod
l = 0
s = pow(2, mod - 2, mod)
for i in range(n - 1):
    ai = a[i]
    inv = pow(ai, mod - 2, mod)
    for _ in range(2):
        s *= inv
        s %= mod
    c = ai * (ai - 1) % mod * s % mod
    s *= ai
    s %= mod
    for j in range(l, 2 * n - 2):
        ans[j - l] += c * dp[j] % mod
        ans[j - l] %= mod
    l += 2
    bi = b[i]
    for j in range(i, n - 1):
        bj = 2 * b[j] % mod if i ^ j else b[j]
        dp[i + j + 1] -= bi * bj % mod
        dp[i + j + 1] %= mod
sys.stdout.write(' '.join(map(str, ans)))

Solution (Python):
mod = 10 ** 9 + 7
n = int(input())
a = [1] + list(map(int, input().split())) + [1]
ans = [0] * (2 * n)
cnt = [1]
for i in a[1:]:
    cnt.append(cnt[-1] * i % mod)
dp = [0] * 2 * n
for i in range(n):
    for j in range(1, 2 * n):
        ans[j] += cnt[i] * dp[j]
        ans[j] %= mod
    ndp = [0] * 2 * n
    for j in range(2 * n - 1):
        ndp[j + 1] = dp[j]
    res = 1
    c = (a[i + 1] - 1) * pow(a[i + 1], mod - 2, mod) % mod
    for j in range(i + 1, n):
        res *= a[j]
        res %= mod
        ndp[j - i + 1] += res * c
        ndp[j - i + 1] %= mod
        ans[j - i] += cnt[i] * res
        ans[j - i] %= mod
    ndp[1] = 1
    dp = ndp
inv2 = pow(2, mod - 2, mod)
ans = [i * inv2 % mod for i in ans[1:-1]]
print(*ans)

Solution (Python):
mod = 10 ** 9 + 7
n = int(input())
a = [1] + list(map(int, input().split())) + [1]
ans = [0] * (2 * n)
cnt = [1]
for i in a[1:]:
    cnt.append(cnt[-1] * i % mod)
dp = [0] * 2 * n
for i in range(n):
    for j in range(1, 2 * n):
        ans[j] += cnt[i] * dp[j]
        ans[j] %= mod
    ndp = [0] * 2 * n
    for j in range(2 * n - 1):
        ndp[j + 1] = dp[j]
    res = 1
    c = (a[i + 1] - 1) * pow(a[i + 1], mod - 2, mod) % mod
    for j in range(i + 1, n):
        res *= a[j]
        res %= mod
        ndp[j - i + 1] += res * c
        ndp[j - i + 1] %= mod
        ans[j - i] += cnt[i] * res
        ans[j - i] %= mod
    ndp[1] = 1
    dp = ndp
inv2 = pow(2, mod - 2, mod)
ans = [i * inv2 % mod for i in ans[1:-1]]
print(*ans)