昨天学了下树分治,今天补这道题,还是太不熟练了,写完之后一直超时。后来查出好多错= =比如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. VC 最爱问的问题:你这个创业项目,如果腾讯跟进了,而且几乎是产品上完全复制,你会怎么办?

    VC 最爱问的问题:你这个创业项目,如果腾讯跟进了,而且几乎是产品上完全复制,你会怎么办? http://www.zhihu.com/question/19607233 朱继玉,独立精神,自由思想. ...

  2. Python天天美味(15) - Python正则表达式操作指南(re使用)(转)

    http://www.cnblogs.com/coderzh/archive/2008/05/06/1185755.html 简介 Python 自1.5版本起增加了re 模块,它提供 Perl 风格 ...

  3. Binding to the Most Recent Visual Studio Libraries--说的很详细,很清楚

    Every version of Visual Studio comes with certain versions of the Microsoft libraries, such as the C ...

  4. hdu 4658 Integer Partition

    五角数定理!!可以参考这个http://www.cnblogs.com/xin-hua/p/3242428.html  代码如下: #include<iostream> #include& ...

  5. socket编程中write、read和send、recv之间的区别

    http://blog.csdn.net/petershina/article/details/7946615 一旦,我们建立好了tcp连接之后,我们就可以把得到的fd当作文件描述符来使用. 由此网络 ...

  6. PHP-CGI, FastCGI, PHP-FPM的关系和区别

    Web server(apache, nginx) 接受到一个php请求后要解析php文件, 怎么解析呢, web server是C语言写的, 所以需要一个协议, 一个php解释器, 也就是CGI. ...

  7. Ubuntu Telnet 配置(openbsd-inetd)

    Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式.可以通过Telnet实现远程登录Ubuntu,但是Ubuntu 10.10默认没有安装Telnet,需 ...

  8. MySQL数据库乱码 - Linux下乱码问题一

    乱码问题是很让人抓狂的问题,下面我将记录一下linux下mysql乱码问题的解决方法. mysql在linux下乱码问题 一.操作 mysql默认字符集是latin1,但是我们大部分程序使用的字符集是 ...

  9. IPC是什么意思?

    IPC(Inter-Process Communication,进程间通信)IPC ( Instruction per Clock 及CPU每一时钟周期内所执行的指令多少) IPC代表了一款处理器的设 ...

  10. 【HDOJ】1914 The Stable Marriage Problem

    稳定婚姻问题,Gale-Shapley算法可解. /* 1914 */ #include <iostream> #include <sstream> #include < ...