昨天学了下树分治,今天补这道题,还是太不熟练了,写完之后一直超时。后来查出好多错= =比如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. DJANGO结合jQuery cxSelect 作二级菜单过滤

    EN,到这个阶段,基本功能算是完成了. 使用了jQuery cxSelect这个插件. http://code.ciaoca.com/jquery/cxselect/ 相关代码如下: html: &l ...

  2. c++ 成员指针函数 实现委托----跨平台实现(复杂)

    牛逼: c++ 牵涉到的技术细节太多了,为了实现一个委托,他妈都搞到汇编里面去了... 总结 为了解释一小段代码,我就得为这个语言中具有争议的一部分写这么一篇长长的指南.为了两行汇编代码,就要做如此麻 ...

  3. linux 2.6 互斥锁的实现-源码分析

    http://blog.csdn.net/tq02h2a/article/details/4317211 看了看linux 2.6 kernel的源码,下面结合代码来分析一下在X86体系结构下,互斥锁 ...

  4. POJ3278——Catch That Cow(BFS)

    Catch That Cow DescriptionFarmer John has been informed of the location of a fugitive cow and wants ...

  5. C#如何在派生类中不显示父类的一些属性以及TypeDescriptor使用

    public SonClass:FatherClass { 定义属性 .... } Type thisType = typeof(SonClass);方法一: PropertyInfo[] pis = ...

  6. 【Codeforces】#345 Div1

    1. Watchmen1.1 题目描述给$n$个点,求曼哈顿距离等于欧式距离的点对数. 1.2 基本思路由$|x_i-x_j|+|y_i-yj| = \sqrt{(x_i-x_j)^2+(y_i-yj ...

  7. Android开发之点击两次Back键退出App

    Back按键的方法是onKeyDown()方法,重写该方法就可以改变back按键的作用. 实现点击两次Back按键退出app,有两种方法: 方法1. private static boolean is ...

  8. struts2启动报错com/opensymphony/xwork2/spring/SpringObjectFactory.java:220:-1

    好久没有搞struts2,今天配置strut2.2.1,启动时遇到个小问题.记录下. tomcat启动报错: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ...

  9. php 生成类的对象 $a=new test();

    程序 <?php class test { ... } $a=new test(); 1.BNF 范式 start: variable '=' expr ';' expr: new_expr ; ...

  10. 十大流行Linux发行版

    [2013年5月13日 51CTO外电头条]Linux是功能强大的常用操作系统之一,目前它在计算机操作系统领域的发展速度越来越快.它提供了出色的性能和速度.Linux用起来非常稳定而可靠.它还提供了几 ...