昨天学了下树分治,今天补这道题,还是太不熟练了,写完之后一直超时。后来查出好多错= =比如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. 10 things you should know about NoSQL databases

    For a quarter of a century, the relational database (RDBMS) has been the dominant model for database ...

  2. POJ3204+DInic+maxflow

    Dinic+maxflow题意:找这样一种边的个数,就是增加该边的容量,可以使得最大流变大思路:求maxflow,再枚举流量为0的边,增加容量,看是否能找到增广路径. /* Dinic+maxflow ...

  3. MySql不同版本安装

    1.win7 64位下如何安装配置mysql-5.7.4-m14-winx64  1. mysql-5.7.4-m14-winx64.zip下载 2.解压到D:/mysql.(路径自己指定) 3.在D ...

  4. 【mysql的设计与优化专题(3)】字段类型与合理的选择字段类型

    本篇博客稍微有点长,它实际上包括两个内容:一是mysql字段类型的介绍,二是在mysql建表过程中是如何正确选择这些字段类型; 字段类型 数值 MySQL 的数值数据类型可以大致划分为两个类别,一个是 ...

  5. 【mysql的编程专题⑥】视图

    视图是表的一个映射,是一张虚表,在结构上视图和普通的表没什么区别,一样可以用sql语句来增删改查; 视图创建后是一直存在数据库内 操作 创建视图 语法 CREATE [ALGORITHM]={UNDE ...

  6. Android:控件布局(单帧布局)FrameLayout

    FrameLayout:所有控件位于左上角,并且直接覆盖前面的子元素. 在最上方显示的层加上: android:clickable="true" 可以避免点击上层触发底层. 实例: ...

  7. DBNull.Value 字段的用法

    DBNull 是一个单独的类,这意味着该类只能存在此实例.它指数据库中数据为空(<NULL>)时,在.net中的值 如果数据库字段的数据缺失,则您可以使用 DBNull.Value 属性将 ...

  8. Armitage初始化

    Kali2.0 Armitage初始化步骤如下 (1)点击页面的Armitage按钮 (2)提示Metasploit RPC server is not running,是否启动该服务,选择是 (3) ...

  9. (组合数学3.1.2.1)POJ 2249 Binomial Showdown(排列组合公式的实现)

    /* * POJ_2249.cpp * * Created on: 2013年10月8日 * Author: Administrator */ #include <iostream> #i ...

  10. CCS学习资料汇总

    2013-06-20 10:31:52 CSDN无网无痕的专栏,有比较多的关于DSP的文章: http://blog.csdn.net/zzsfqiuyigui/article/details/694 ...