• 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<<'
    ';
    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;
    } 
  • 相关阅读:
    排序算法<No.3>【桶排序】
    排序算法<No.2>【快速排序】
    排序算法<No.1> 【计数排序】
    排序问题思考(要求时间和空间复杂度尽可能的低)【Part 1】
    elasticsearch【cat API,系统数据】指令汇总
    netty研究【1】:编译源代码
    D3树状图给指定特性的边特别显示颜色
    zabbix3.0安装之图形界面显示异常【server】
    计算一维组合数的java实现
    zabbix3.0安装【server】
  • 原文地址:https://www.cnblogs.com/shenben/p/10424160.html
Copyright © 2020-2023  润新知