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.一个结点能走多次,树形的最大特点是到达后继的路径是唯一的,那个如果一个结点无法往子结点走,那么子结点就不用考虑了. 有的结点不能走完它的子结点,而有的可能走完他的子节点以后还会剩下一些 ...
随机推荐
- osgi学习
Bundle可以被动态地安装.启动.停止和卸载.Bundle是服务(Service)和组件(Component)的载体.在OSGi中,每个Bundle都有自己独立于其他Bundle的ClassLoad ...
- c_test
1.int a[][4]={0,0};与int a[3][4] = {0}; 元素不够的就以位模式初始化为0 a[第一维][第二维] 的大小,也就是最多存几个 int a[][3]={1,2,3,4, ...
- hdu 5653 Bomber Man wants to bomb an Array
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5653 题意:已知炸弹可以炸掉左边L个位置,右边R个位置,那么炸点炸掉的总数是L+R+1.给定每个炸弹的 ...
- Android 反编译 -- apktool、dex2jar、jd-gui
原文:http://blog.csdn.net/vipzjyno1/article/details/21039349/ apktool 最新官网: http://ibotpeaches.github. ...
- Nginx反向代理设置 从80端口转向其他端口
[root@localhost bin]# netstat -lnutp Active Internet connections (only servers) Proto Recv-Q Send-Q ...
- C/C++学习笔记----指针的理解
指针是C/C++编程中的重要概念之一,也是最容易产生困惑并导致程序出错的问题之一.利用指针编程可以表示各种数据结构,通过指针可使用主调函数和被调函数之间共享变量或数据结构,便于实现双向数据通讯:指针能 ...
- SessionState详解 session有效期时间:默认20分
为当前应用程序配置会话状态设置. configuration 元素(常规设置架构) system.web 元素(ASP.NET 设置架构) sessionState 元素(ASP.NET ...
- 12.享元模式(Flyweight Pattern)
using System; using System.Collections; namespace ConsoleApplication5 { class Program { /// <summ ...
- 最稳定 性能最好 的 Linux 版本?
Ubuntu太他妈不稳定了,简直是一坨屎 CentOS.Ubuntu.Debian三个linux比较异同http://blog.csdn.net/educast/article/details/383 ...
- protobuf-net 对象二进制序列化与反序列号(转)
概述: Protobuf是google开源的一个项目,用户数据序列化反序列化,google声称google的数据通信都是用该序列化方法.它比xml格式要少的多,甚至比二进制数据格式也小的多. Prot ...