Codeforces 543D. Road Improvement (树dp + 乘法逆元)
2016-09-27 16:06
471 查看
题目链接:http://codeforces.com/contest/543/problem/D
给你一棵树,初始所有的边都是坏的,要你修复若干边。指定一个root,所有的点到root最多只有一个坏边。以每个点为root,问分别有多少种方案数。
dp[i]表示以i为子树的root的情况数,不考虑父节点,考虑子节点。 dp[i] = dp[i] * (dp[i->son] + 1)
up[i]表示以i为子树的root的情况数(倒着的),考虑父节点,不考虑子节点。 这里需要逆元。 注意(a/b)%mod中b%mod=0是错误的,所以要特殊判断。
给你一棵树,初始所有的边都是坏的,要你修复若干边。指定一个root,所有的点到root最多只有一个坏边。以每个点为root,问分别有多少种方案数。
dp[i]表示以i为子树的root的情况数,不考虑父节点,考虑子节点。 dp[i] = dp[i] * (dp[i->son] + 1)
up[i]表示以i为子树的root的情况数(倒着的),考虑父节点,不考虑子节点。 这里需要逆元。 注意(a/b)%mod中b%mod=0是错误的,所以要特殊判断。
//#pragma comment(linker, "/STACK:102400000, 102400000") #include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <vector> #include <cmath> #include <ctime> #include <list> #include <set> #include <map> using namespace std; typedef long long LL; typedef pair <int, int> P; const int N = 2e5 + 5; LL dp , mod = 1e9 + 7, up ; vector <int> edge ; int cnt ; //子树(dp[i->son] + 1)%mod != 0的节点数 LL fuck ; //子树(dp[i-son] + 1)%mod != 0的方案数相乘 LL fpow(LL a, LL n) { LL res = 1; while(n) { if(n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; } void dfs1(int u, int p) { dp[u] = 1; fuck[u] = 1; for(int i = 0; i < edge[u].size(); ++i) { int v = edge[u][i]; if(v == p) continue; dfs1(v, u); if(dp[v] + 1 == mod) cnt[u]++; else fuck[u] = (1 + dp[v]) % mod * fuck[u] % mod; dp[u] = (1 + dp[v]) % mod * dp[u] % mod; } } void dfs2(int u, int p) { for(int i = 0; i < edge[u].size(); ++i) { int v = edge[u][i]; if(v == p) continue; //LL temp = dp[u] * fpow((dp[v] + 1) % mod, mod - 2) % mod; //error LL temp = 0; if(dp[v] + 1 == mod && up[u] && cnt[u] == 1) { //特殊情况 temp = fuck[u]; } else { temp = dp[u] * fpow((dp[v] + 1) % mod, mod - 2) % mod; } up[v] = (up[u] * temp % mod + 1) % mod; dfs2(v, u); } } int main() { int n, u; scanf("%d", &n); for(int i = 2; i <= n; ++i) { scanf("%d", &u); edge[i].push_back(u); edge[u].push_back(i); } dfs1(1, -1); up[1] = 1; dfs2(1, -1); for(int i = 1; i <= n; ++i) { printf("%lld%c", dp[i]*up[i]%mod, i == n ? '\n': ' '); } return 0; }
相关文章推荐
- Codeforces 543D Road Improvement(树形DP + 乘法逆元)
- [CodeForces 118D]Caesar's Legions[DP]
- Codeforces 55D Beautiful Number (数位dp)
- codeforces 366C C. Dima and Salad(dp)
- codeforces 176 B. Word Cut(DP)
- Codeforces 321E Ciel and Gondolas(DP)
- 【CodeForces 118D】【DP】 Caesar's Legions 【n1种步兵n2种马兵,询问多少种排列方式使不超过k1种步兵相连k2种马兵相连】
- Codeforces 453B Little Pony and Harmony Chest 状压dp
- Codeforces 337 D Book of Evil(树形dp,两遍dfs)
- Codeforces 624D Array Gcd(数论+dp)
- Codeforces 488D Strip (set+DP)
- codeforces 208C 图的拓扑排序+简单DP
- Codeforces 401D Roman and Numbers 状压DP
- Codeforces 479E Riding in a Lift【Dp+前缀和优化+二分】好题~
- codeforces 401D (数位DP)
- codeforces 16 E 简单概率DP
- codeforces 418B. Cunning Gena (状态dp)
- codeforces 768 D Jon and Orbs(概率dp)
- Codeforces 711C 树DP 解题报告
- 【codeforces】543D. Road Improvement【树形DP】