昨天学了下树分治,今天补这道题,还是太不熟练了,写完之后一直超时。后来查出好多错= =比如v,u写倒了,比如+写成了取最值,比如。。。。爆int。。。查了两个多小时的错。。哭。。。(没想到进首页了

http://hzwer.com/6107.html 大神博客,代码清晰,照着这个改的

逆元预处理之前是没有见过的,学习了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>
typedef long long ll;
using namespace std; const int N = ;
const int MOD = ;
inline int read()
{
int x=;char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x;
}
struct Edge {
int to, next;
} edge[N*];
int head[N];
int edge_cnt; int a[N], sz[N], inv[MOD];
bool used[N];
int root, minsz, size;
int ansx, ansy;
int tmp[N], id[N], cnt;
int mp[MOD];
int n, k; void up(int &x, int y) { if(y>x) x=y; } void query(int v, int x) {
int ser = (ll)k*inv[v]%MOD;
int y = mp[ser];
if (y == || x == y) return ;
if (y < x) swap(x, y);
if (x < ansx ||(x == ansx && y < ansy)) ansx=x, ansy=y;
} void add_edge(int u, int v) {
edge[edge_cnt].to = v;
edge[edge_cnt].next = head[u];
head[u] = edge_cnt++;
} void get_root(int u, int fa) {
sz[u] = ;
int maxn= ;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (v == fa || used[v]) continue;
get_root(v, u);
sz[u] += sz[v];
up(maxn, sz[v]);
}
up(maxn, size-sz[u]);
if (maxn < minsz) minsz=maxn, root=u;
} void dfs(int u, int fa, int val) {
tmp[cnt] = val; id[cnt++] = u;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (v == fa || used[v]) continue;
dfs(v, u, (ll)val*a[v]%MOD);
}
} void solve(int u) {
used[u] = true;
mp[ a[u] ] = u;
// 计算经过u的所有乘积为k的点对
// 对每一个子节点处理 防止找的的点对是同一个子树的
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (used[v]) continue;
cnt = ; dfs(v, u, a[v]);
for (int j = ; j < cnt; ++j) query(tmp[j], id[j]);
for (int j = ; j < cnt; ++j) {
tmp[j] = (ll)tmp[j]*a[u]%MOD;
int &now = mp[tmp[j]];
if (now == || now > id[j]) mp[tmp[j]]=id[j];
}
}
// 删除所有记录 因为处理子树内时相互没有影响
mp[a[u]] = ;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (used[v]) continue;
cnt = ; dfs(v, u, (ll)a[v]*a[u]%MOD);
for (int j = ; j < cnt; ++j) {
mp[tmp[j]] = ;
}
}
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (used[v]) continue;
size = sz[v]; minsz = n+;
get_root(v, );
solve(root);
}
}
int main() { inv[]=;
for(int i=;i<MOD;i++)
{
int a=MOD/i,b=MOD%i;
inv[i]=((ll)inv[b]*(-a)%MOD+MOD)%MOD;
}
while (~scanf("%d%d", &n, &k)) {
for (int i = ; i <= n; ++i) a[i] = read();
int u, v;
memset(head, -, sizeof head);
edge_cnt = ;
memset(used, , sizeof used);
for (int i = ; i < n; ++i) {
u = read(); v = read();
add_edge(u, v);
add_edge(v, u);
}
minsz = n+; size = n;
get_root(, );
ansx = ansy = MOD;
solve(root);
if (ansx == MOD) puts("No solution");
else printf("%d %d\n", ansx, ansy);
}
return ;
}

hdu4812-D Tree (树的点分治)的更多相关文章

  1. hdu 4812 D Tree(树的点分治)

    D Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total ...

  2. 【poj1741】Tree 树的点分治

    题目描述 Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dis ...

  3. POJ1741——Tree(树的点分治)

    1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-11-17 1 ...

  4. 【POJ 1741】 Tree (树的点分治)

    Tree   Description Give a tree with n vertices,each edge has a length(positive integer less than 100 ...

  5. POJ 1741 Tree(树的点分治,入门题)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21357   Accepted: 7006 Description ...

  6. HDU 4670 Cube number on a tree ( 树的点分治 )

    题意 : 给你一棵树 . 树的每一个结点都有一个权值 . 问你有多少条路径权值的乘积是一个全然立方数 . 题目中给了你 K 个素数 ( K <= 30 ) , 全部权值都能分解成这k个素数 思路 ...

  7. HDU4812 D Tree(树的点分治)

    题目大概说给一棵有点权的树,输出字典序最小的点对,使这两点间路径上点权的乘积模1000003的结果为k. 树的点分治搞了.因为是点权过根的两条路径的LCA会被重复统计,而注意到1000003是质数,所 ...

  8. poj 1741 Tree(树的点分治)

    poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出 ...

  9. POJ 1741 Tree 树的分治(点分治)

    题目大意:给出一颗无根树和每条边的权值,求出树上两个点之间距离<=k的点的对数. 思路:树的点分治.利用递归和求树的重心来解决这类问题.由于满足题意的点对一共仅仅有两种: 1.在以该节点的子树中 ...

随机推荐

  1. dll的概念 dll导出变量 函数 类

    1. DLL的概念 DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数.变量或类.这些可以直接拿来使用. 静态链接库与动态链接库的区别:   (1)静态链接 ...

  2. linux命令补全 忘记命令只记得开头

    linux的shell不仅提供上下箭头来翻阅历史使用过的命令,还提供命令补全功能. 例如,你想创建一个文件夹,只记得是m开头的命令,此时可以: ①输入m ②按键盘上的Tab键两次 (有可能还出现这句话 ...

  3. 看文档要看仔细,英语要加强啊... cocos2d-x 的 API 和 对应版本的 cocos2d-js 的 API 没有完全对应

    /** * Sets the X rotation (angle) of the node in degrees which performs a horizontal rotational skew ...

  4. java中dao层和service层的区别是什么?

    首先解释面上意思,service是业务层,dao是数据访问层.呵呵,这个问题我曾经也有过,记得以前刚学编程的时候,都是在service里直接调用dao,service里面就new一个dao类对象,调用 ...

  5. 易企秀 we+ Maka 兔展 四大H5页面制作工具

    H5这个由HTML5简化而来的词汇,正通过微信广泛传播.H5是集文字.图片.音乐.视频.链接等多种形式的展示页面,丰富的控件.灵活的动画特效.强大的交互应用和数据分析,高速低价的实现信息传播,非常适合 ...

  6. Autodesk 2015全套密钥

    Below is a list for collecting all the Autodesk 2015 Product Keys:      [*]AutoCAD 2015 001G1      [ ...

  7. python 操作符笔记:

    操作符 描述 x if y else z 三元描述(2.5新加)(类似于c中的 x?y:z x or y 或 x and y 与 not x 非 x!=y ,x is y 序列成员测试 x | y 位 ...

  8. poj 1840 Eqs (hash)

    题目:http://poj.org/problem?id=1840 题解:http://blog.csdn.net/lyy289065406/article/details/6647387 小优姐讲的 ...

  9. NLog 传递参数

    用NLog记文件日志,一般都用{$basedir}变量,把日志记在运行的目录或者它的子目录下,遇到要写在其他目录的下,看了下Nlog找到用环境变量传参数. .net 里写 Environment.Se ...

  10. NET SCADA软件简介

    Scada是一款采用.Net WPF开发的免费组态软件,功能强大,支持服务器客户端方式运行.支持浏览器运行,软件非常小巧,免安装,支持Modbus和OPC通讯协议, 开放构架,支持C#.Net脚本,J ...