Codeforces 543D Road Improvement(树形DP + 乘法逆元)
题目大概说给一棵树,树的边一开始都是损坏的,要修复一些边,修复完后要满足各个点到根的路径上最多只有一条坏的边,现在以各个点为根分别求出修复边的方案数,其结果模1000000007。
不难联想到这题和HDU2196是一种类型的树形DP,因为它们都要分别求各个点的答案。然后解法也不难想:
- dp0[u]表示只考虑以u结点为根的子树的方案数
- dp1[u]表示u结点往上走,倒过来,以它父亲为根那部分的方案数
有了这两部分的结果,对于各个点u的答案就是dp0[u]*(dp1[u]+1)。这两部分求法如下,画画图比较好想:
- 首先求出dp0,这个转移是:dp0[u]=∏(dp0[v]+1)(v是u的孩子),就是对于每个孩子为根的子树的情况总数的乘积,而其中每个孩子的情况总数还要加上一个父亲到孩子之间的边不修复、孩子的子树的边全部修复的情况。
- 然后求出dp1,转移:求dp1[v],u是v的父亲,dp1[v]=dp0[u]/dp0[v]*(dp1[u]+1)。
- 现在问题来了,求dp0[u]/dp0[v],注意到结果模1000000007是一个质数,一开始我用乘法逆元WA了,因为虽然1000000007是质数,但1000000007的倍数不与1000000007互质,模1000000007结果是0,这样就出问题了!
- 本来我想改用线段树做,不过队友提醒说可以分情况讨论,如果不存在与1000000007不互质的数直接逆元搞,存在两个以上不与1000000007互质的数那结果就是0,一个的话。。。。。我就不多说了。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 222222
struct Edge{
int v,next;
}edge[MAXN<<];
int NE,head[MAXN];
void addEdge(int u,int v){
edge[NE].v=v; edge[NE].next=head[u];
head[u]=NE++;
}
long long d[][MAXN];
long long ine(long long a){
long long res=;
int n=-;
while(n){
if(n&){
res*=a;
res%=;
}
a*=a;
a%=;
n>>=;
}
return res;
}
void dp0(int u,int fa){
long long res=;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue;
dp0(v,u);
res*=d[][v]+;
res%=;
}
d[][u]=res;
}
void dp1(int u,int fa){
int cnt=;
long long tot=;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue;
if((d[][v]+)%==) ++cnt;
else{
tot*=d[][v]+;
tot%=;
}
}
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue;
if(cnt){
if((d[][v]+)%== && cnt==){
d[][v]=tot;
}else d[][v]=;
}else{
d[][v]=d[][u]*ine((d[][v]+)%);
d[][v]%=;
}
d[][v]*=d[][u]+;
d[][v]%=;
dp1(v,u);
}
}
int main(){
memset(head,-,sizeof(head));
int n,a;
scanf("%d",&n);
for(int i=; i<=n; ++i){
scanf("%d",&a);
addEdge(a,i);
addEdge(i,a);
}
dp0(,);
dp1(,);
for(int i=; i<=n; ++i){
printf("%lld ",d[][i]*(d[][i]+)%);
}
return ;
}
Codeforces 543D Road Improvement(树形DP + 乘法逆元)的更多相关文章
- Codeforces 543D. Road Improvement (树dp + 乘法逆元)
题目链接:http://codeforces.com/contest/543/problem/D 给你一棵树,初始所有的边都是坏的,要你修复若干边.指定一个root,所有的点到root最多只有一个坏边 ...
- Codeforces 543D Road Improvement(DP)
题目链接 Solution 比较明显的树形DP模型. 首先可以先用一次DFS求出以1为根时,sum[i](以i为子树的根时,满足要求的子树的个数). 考虑将根从i变换到它的儿子j时,sum[i]产生的 ...
- Codeforces Round #302 (Div. 1) D - Road Improvement 树形dp
D - Road Improvemen 思路:0没有逆元!!!! 不能直接除,要求前缀积和后缀积!!! #include<bits/stdc++.h> #define LL long lo ...
- Codeforces 543D Road Improvement
http://codeforces.com/contest/543/problem/D 题意: 给定n个点的树 问: 一开始全是黑边,对于以i为根时,把树边白染色,使得任意点走到根的路径上不超过一条黑 ...
- codeforces 212E IT Restaurants(树形dp+背包思想)
题目链接:http://codeforces.com/problemset/problem/212/E 题目大意:给你一个无向树,现在用两种颜色去给这颗树上的节点染色.用(a,b)表示两种颜色分别染的 ...
- Codeforces 123E Maze(树形DP+期望)
[题目链接] http://codeforces.com/problemset/problem/123/E [题目大意] 给出一棵,给出从每个点出发的概率和以每个点为终点的概率,求出每次按照dfs序从 ...
- BZOJ 1004: [HNOI2008]Cards( 置换群 + burnside引理 + 背包dp + 乘法逆元 )
题意保证了是一个置换群. 根据burnside引理, 答案为Σc(f) / (M+1). c(f)表示置换f的不动点数, 而题目限制了颜色的数量, 所以还得满足题目, 用背包dp来计算.dp(x,i, ...
- codeforces 709E E. Centroids(树形dp)
题目链接: E. Centroids time limit per test 4 seconds memory limit per test 512 megabytes input standard ...
- CodeForces 77C Beavermuncher-0xFF (树形dp)
不错的树形dp.一个结点能走多次,树形的最大特点是到达后继的路径是唯一的,那个如果一个结点无法往子结点走,那么子结点就不用考虑了. 有的结点不能走完它的子结点,而有的可能走完他的子节点以后还会剩下一些 ...
随机推荐
- Javascript异步编程方法总结
现在我们有三个函数,f1, f2, f3 按正常的思路我们会这样写代码: function f1 (){}; function f2 (){}; function f3 (){}; //在这里调用函数 ...
- Web.Config如何输入特殊字符
- gcc创建和使用静态库、动态库
http://www.cnblogs.com/dyllove98/archive/2013/06/25/3155599.html 目录树结构: test/include/hello.h #ifdef ...
- REORG TABLESPACE on z/os
这个困扰了我两天的问题终于解决了,在运行这个job时:总是提示 A REQUIRED DD CARD OR TEMPLATE IS MISSING NAME=SYSDISC A REQUIRED DD ...
- NMON中的各项参数指标
一.NMON中的各项参数指标: SYS_SUMM:显示当前服务器的总体性能情况 Total System I/OStatistics:Avg tps during an interval:显示采集间隔 ...
- php上传文件进度条
ps:本文转自脚本之家 Web应用中常需要提供文件上传的功能.典型的场景包括用户头像上传.相册图片上传等.当需要上传的文件比较大的时候,提供一个显示上传进度的进度条就很有必要了. 在PHP 5.4以前 ...
- JS中级 - 01:DOM节点
1元素属性 1.1childNodes 返回元素的一个子节点的数组 (不推荐,建议用非标准children代替) 提醒:只包含一级子节点,不包含后辈孙级别以下节点. children:返回元素的一 ...
- C#的扩展方法
using System; using System.Collections; using System.Collections.Generic; using System.IO; using Sys ...
- 15.命令模式(Command Pattern)
using System; namespace ConsoleApplication8 { class Program { /// <summary> /// 在软件系统中,“行为请求者” ...
- 菜鸟学Linux命令:nohup命令启动程序
在UNIX/LINUX中,普通进程用&符号放到后台运行,如果启动该程序的控制台logout,则该进程随即终止. 要实现守护进程,一种方法是按守护进程的规则去编程,比较麻烦:另一种方法是仍然用普 ...