• Codeforces 954H Path Counting(DP)


    题目链接  Path Counting

    题意  给定一棵高度为$n$的树,给出每一层的每个点的儿子个数(某一层的所有点儿子个数相同)。

        令$f_{k}$为长度为$k$的路径条数,求$f_{1}, f_{2}, ..., f_{2n-2}$。

     

    考虑DP,设$f[i][j]$为从深度为$i$的点出发背对以$i$为根的子树(即任何时候都不进入以$i$为根的子树)走$j$步之后可以到达的点的个数。

    (同一条边最多走一次)

    那么$f[i][j] = f[i-1][j-1] + calc(i-1, j-1)$, $calc(i, j)$为从$i$点出发往以$i$为根的子树走$j$步能到达的点的个数。

    然后这一层对答案的贡献即为$f[i][j] * g[i]$($g[i]$为第$i$层结点个数)

    我们会发现这样那些一个点为另一个点的祖先的路径只统计了一次,其他路径统计了两次。

    为了一致我们再求一遍前者类型路径的个数,加起来除以$2$即可。

    时间复杂度$O(n^{2})$

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    const int N = 5e3 + 10;
    const int mod = 1e9 + 7;
    const int rev = 5e8 + 4;
    
    int a[N << 1], f[N][N << 1];
    int num[N << 1], c[N << 2], s[N << 1], inv[N << 1];
    int ans[N << 1];
    int n;
    
    inline int Pow(int a, int b, int mod){
            int ret = 1;
            for (; b; b >>= 1, a = 1ll * a * a % mod) if (b & 1) ret = 1ll * ret * a % mod;
            return ret;
    }
    
    
    int calc(int x, int y){
    	int ret = (a[x] + mod - 1) % mod;
    	ret = 1ll * ret * c[x + y - 1] % mod;
    	ret = 1ll * ret * inv[x] % mod;
    	return ret;
    }
    
    
    int main(){
    
    	scanf("%d", &n);
    	rep(i, 1, n - 1) scanf("%d", a + i);
    
    	num[1] = 1; 
    	rep(i, 2, n) num[i] = 1ll * num[i - 1] * a[i - 1] % mod;
    
    	c[0] = 1;
    	rep(i, 1, n) c[i] = 1ll * c[i - 1] * a[i] % mod;
    
    	rep(i, 1, n) inv[i] = Pow(c[i], mod - 2, mod);
    
    	s[0] = 0;
    	rep(i, 1, n) s[i] = (s[i - 1] + num[i]) % mod;
    
    	rep(i, 2, n){
    		f[i][1] = 1;
    		rep(j, 2, 2 * n - 2){
    			f[i][j] = (1ll * f[i - 1][j - 1] + calc(i - 1, j - 1)) % mod;
    		}
    	}
    
    	rep(i, 1, 2 * n - 2){
    		rep(j, 1, n){
    			ans[i] = (1ll * ans[i] + 1ll * f[j][i] * num[j]) % mod;
    		}
    	}
    
    	rep(i, 1, n - 1){
    		ans[i] = (ans[i] + s[n]) % mod;
    		ans[i] = (ans[i] - s[i] + mod) % mod;
    	}
    
    	rep(i, 1, 2 * n - 2) ans[i] = 1ll * ans[i] * rev % mod;
    	rep(i, 1, 2 * n - 2) printf("%d
    ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    edu_2_4_1
    edu_2_3_2
    edu_2_3_1
    edu_2_2_2
    edu_2_1_1
    edu_2_2_1
    hdu 1270 小希的数表
    hdu 2151 worm
    hdu1089 Ignatius's puzzle
    hdu 2190 悼念512汶川大地震遇难同胞——重建希望小学
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/8663279.html
Copyright © 2020-2023  润新知