CodeForces 543d Road Improvement

Road Improvement

Time Limit: 2000ms

Memory Limit: 262144KB

This problem will be judged on CodeForces. Original ID: 543D
64-bit integer IO format: %I64d      Java class name: (Any)

The country has n cities and n - 1 bidirectional roads, it is possible to get from every city to any other one if you move only along the roads. The cities are numbered with integers from1 to n inclusive.

All the roads are initially bad, but the government wants to improve the state of some roads. We will assume that the citizens are happy about road improvement if the path from the capital located in city x to any other city contains at most one bad road.

Your task is — for every possible x determine the number of ways of improving the quality of some roads in order to meet the citizens‘ condition. As those values can be rather large, you need to print each value modulo 1 000 000 007 (109 + 7).

Input

The first line of the input contains a single integer n (2 ≤ n ≤ 2·105) — the number of cities in the country. Next line contains n - 1 positive integers p2, p3, p4, ..., pn (1 ≤ pi ≤ i - 1) — the description of the roads in the country. Number pi means that the country has a road connecting city pi and city i.

Output

Print n integers a1, a2, ..., an, where ai is the sought number of ways to improve the quality of the roads modulo 1 000 000 007 (109 + 7), if the capital of the country is at city number i.

Sample Input

Input

31 1

Output

4 3 3

Input

51 2 3 4

Output

5 8 9 8 5

Source

Codeforces Round #302 (Div. 1)

解题:树形dp

dp[u]表示以u为根的方案数,dp[u] = (dp[v]+1)*(dp[v2]+1)...

为什么加1?因为如果u到v的路修的话就是dp[v],如果不修,那么只有1种方案,子树都要修

那么我们如何计算任意点位根的数量呢

假设当前早在v 其父亲为u dp2[u]表示以u为根倒回去的方案数,那么以为根的方案数是多少?

很显然我们要计算出v的兄弟的方案数,(dp[v]+1)*(dp[v2]+1)...

乘上u倒回去的方案数

就是去掉v这棵树 以u为根的方案数,

现在加上v

u到v的边可以修,那么就是前面的方案数,如果不修,那只有一种方案

也就是说前面的积+1后

乘以以v为根的方案数dp[v]。。就是以v为首都的可行方案数

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int maxn = 200010;
 5 vector<int>g[maxn];
 6 LL dp[maxn],dp2[maxn];
 7 const LL mod = 1000000007;
 8 void dfs(int u,int fa){
 9     dp[u] = 1;
10     for(int i = g[u].size()-1; i >= 0; --i){
11         if(g[u][i] == fa) continue;
12         dfs(g[u][i],u);
13         dp[u] = dp[u]*(dp[g[u][i]]+1)%mod;
14     }
15 }
16 LL L[maxn],R[maxn];
17 void dfs2(int u,int fa){
18     int m = g[u].size();
19     L[0] = 1;
20     R[m - 1] = dp2[u];
21     for(int i = 1; i < m; ++i)
22         L[i] = L[i-1]*(dp[g[u][i-1]]+1)%mod;
23     for(int i = m-2; i >= 0; --i)
24         R[i] = R[i+1]*(dp[g[u][i+1]]+1)%mod;
25     for(int i = 0; i < m; ++i){
26         if(g[u][i] == fa) continue;
27         dp2[g[u][i]] = (L[i]*R[i] + 1)%mod;
28     }
29     for(int i = 0; i < m; ++i){
30         if(g[u][i] == fa) continue;
31         dfs2(g[u][i],u);
32     }
33 }
34 int main(){
35     int n,o;
36     scanf("%d",&n);
37     for(int i = 2; i <= n; ++i){
38         scanf("%d",&o);
39         g[o].push_back(i);
40     }
41     dp2[1] = 1;
42     dfs(1,0);
43     dfs2(1,0);
44     for(int i = 1; i <= n; ++i)
45         cout<<dp2[i]*dp[i]%mod<<(i == n?"\n":" ");
46     return 0;
47 }

时间: 2024-08-03 16:37:17

CodeForces 543d Road Improvement的相关文章

Codeforces 543D Road Improvement(树形DP+乘法逆元)

题目大概说给一棵树,树的边一开始都是损坏的,要修复一些边,修复完后要满足各个点到根的路径上最多只有一条坏的边,现在以各个点为根分别求出修复边的方案数,其结果模1000000007. 不难联想到这题和HDU2196是一种类型的树形DP,因为它们都要分别求各个点的答案.然后解法也不难想: dp0[u]表示只考虑以u结点为根的子树的方案数 dp1[u]表示u结点往上走,倒过来,以它父亲为根那部分的方案数 有了这两部分的结果,对于各个点u的答案就是dp0[u]*(dp1[u]+1).这两部分求法如下,画

Codeforces 543D Road Improvement 树形dp

题目链接:点击打开链接 题意: 给定n个点的树 问: 对于以i为根时,把树边黑白染色,使得任意点走到根的路径上不超过一条黑边,输出染色的方案数(mod 1e9+7) 思路: 显然i点的方案数 = i为根的子树的方案数 * 不包括i为根的子树的部分的方案数 首先以i为根的子树求一个方案数down[i]:for all son vj  of i, down[i] = multiply down[j] 求不包括i子树的时候为了避免除法,对儿子的方案数求一个前缀积和后缀积即可 避免了使用逆元 #incl

Codeforces 543D Road Improvement(DP)

题目链接 Solution 比较明显的树形DP模型. 首先可以先用一次DFS求出以1为根时,sum[i](以i为子树的根时,满足要求的子树的个数). 考虑将根从i变换到它的儿子j时,sum[i]产生的变化. 在变化前sum[i]不为0时,可以用求逆元的方法求出新的sum[i]. sum[i]为0时,就需要遍历i的新的儿子. 官方的题解给出了一个比较好的做法是预处理i的儿子的前缀积,和后缀积.使用的时候只要去除相应的儿子. #include <bits/stdc++.h> #define LL

Codeforces 729C Road to Cinema(二分)

题目链接 http://codeforces.com/problemset/problem/729/C 题意:n个价格c[i],油量v[i]的汽车,求最便宜的一辆使得能在t时间内到达s,路途中有k个位置在g[i]的加油站,可以免费加满油,且不耗时间.每辆车有两种运行模式可以随时切换:1.每米一分钟两升油:2.每米两分钟一升油. 看到10^5次加上循环两次就想到二分或者线段树或者看错题意了. 这题二分查找一下汽油就可以了,找到最少多少汽油够到达,然后再for一遍找汽油量大的且价格便宜的车即可. 还

CodeForces 34D Road Map

给出每个点的父节点,存下来. 再从r2开始,dfs到r1,把这条路径上的所有结点的父节点改变方向就可以了. #include <iostream> #include <cstdlib> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #in

CodeForces 738C Road to Cinema

二分答案. 油量越多,显然通过的时间越少.可以二分找到最小的油量,可以在$t$时间内到达电影院. 一个油箱容量为v的车通过长度为L的路程需要的最小时间为$max(L,3*L-v)$.计算过程如下: 假设普通速度运行了距离$a$,加速运行了距离$b$,则$a+b=L$,即$b=L-a$. 因为$a+2*b≤v$,所以$a≥2*L-v$.所花时间为$2*a+b≥3*L-v$,因为最小需要$L$的时间,所以取个$max$.按照$max(L,3*L-v)$一段一段加起来验证就可以了. #pragma c

[Codeforces 721E]Road to Home

题目大意:有一条长为l的公路(可看为数轴),n盏路灯,每盏路灯有照射区间且互不重叠,有个人要走过这条公路,他只敢在路灯照射的地方唱歌,固定走p唱完一首歌,歌曲必须连续唱否则就要至少走t才能继续唱.问你最多能唱几首歌? 解题思路:一道dp的题目. 首先有一个结论:对于一段区间,你能唱几首歌就唱几首歌. 因为如果你少唱一首歌,在下个区间最多也就多唱一首歌,与你在前面唱这首歌是一样的. 所以我们设f[i]表示前i个区间最多唱的歌的数量,g[i]表示在f[i]的前提下,最早的停止唱歌的位置. 很显然有$

[CF543D]Road Improvement

题目大意:给定一个无根树,给每条边黑白染色,求出每个点为根时,其他点到根的路径上至多有一条黑边的染色方案数,模$1e9+7$. 题解:树形$DP$不难想到,记$f_u$为以$1$为根时,以$u$为根的子树的方案数,$f_u=\prod\limits_{v\in son_u}(f_v+1)$ 换根也很简单. 但是这题卡模数,换根时要求逆元,其中$f_u$可能等于$1e9+6$,加一后变成$0$,无法求逆.可以求前缀积和后缀积转移 卡点:原$dp$写错 C++ Code: #include <cst

Codeforces 1333E Road to 1600

Description 给一个 $n\times n$ 的棋盘,上面有 $n\times n$ 个 $[1,n\times n]$ 之间的整数且互不相同. 棋盘上有一个车和一个后,初始都在数字 $1$ 处. 走法如下: 车能到达同一行或同一列的任何(没有被自己访问过的)位置,后能到达同一行,同一列或同一斜线上任何(没有被自己访问过的)位置; 每次车和后都会走到能到达的数字中最小的.如果不存在,那么会花费 $1$ 的代价传送到整个棋盘中没有被自己访问过的数字最小的位置. 求一种方案,满足车走完的代