HDU 4812 D Tree 树分区+逆+hash新位置
意甲冠军:
特定n点树 K
以下n号码是正确的点
以下n-1行给出了树的侧。
问:
所以,如果有在正确的道路点图的路径 % mod = K
如果输出路径的两端存在。
多条路径则输出字典序最小的一条。
思路:
按树重心分治。
分成路径是否经过树重心。
然后用力码。
。
has[x] = u;
表示乘积为x 相应的点是u
但这样has就不能用计数器来优化清空。
所以用2个数组: has[x] = cnt; has_id[x] = u;
这样has里存的是乘积为x是否存在。has_id[x] 来记录点。
#pragma comment(linker, "/STACK:10240000000000,10240000000000")
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;
const int inf = 10000000;
typedef pair<int,int> pii;
typedef long long ll;
const int mod = 1000000+3;
int ni[mod];
void quick(int x){
int ans = 1, tmp = x, y = mod-2;
while(y){
if(y&1)
ans = (ll)ans * (ll)x % (ll)mod;
x = (ll)x*(ll)x%(ll)mod;
y>>=1;
}
ni[tmp] = ans;
}
template <class T>
inline bool rd(T &ret) {
char c; int sgn;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')? -1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
ret*=sgn;
return 1;
}
template <class T>
inline void pt(T x) {
if (x <0) {
putchar('-');
x = -x;
}
if(x>9) pt(x/10);
putchar(x%10+'0');
}
#define N 100005
pii ans;
void updata(int x, int y){
if(x>y)swap(x,y);
if(ans.first > x || ans.first==x && ans.second > y)
ans = pii(x,y);
}
struct Edge{
int to, nex;
}edge[N<<1];
int head[N], edgenum;
void init(){memset(head,-1,sizeof head); edgenum = 0;}
void add(int u, int v){
Edge E = {v,head[u]};
edge[edgenum] = E;
head[u] = edgenum++;
}
int a[N], K, mul[N];
int n, siz[N];
int s[N], id[N], top;
int has[mod], has_id[mod], tim;
bool vis[N];
void add_hash(int u, int multi_ans){
if(has[multi_ans] == tim)
has_id[multi_ans] = min(has_id[multi_ans], u);
else {
has[multi_ans] = tim;
has_id[multi_ans] = u;
}
}
int wval, wroot;
void getroot(int u, int fa){
siz[u] = 1;
int maxv = 0;
for(int i = head[u]; ~i; i = edge[i].nex){
int v = edge[i].to; if(v == fa || vis[v])continue;
getroot(v, u);
siz[u] += siz[v];
maxv = max(maxv, siz[v]);
}
maxv = max(maxv, siz[0] - siz[u]);
if(maxv < wval)wval = maxv, wroot = u;
}
int find_root(int u, int fa){ //找到子树的重心
wval = 1000000;
getroot(u, fa);
return wroot;
} void multi(int u, int fa){
mul[u] = ((ll)a[u]*(ll)mul[fa])%(ll)mod;
siz[u] = 1;
s[top] = mul[u]; id[top++] = u;
for(int i = head[u];~i;i=edge[i].nex){
int v = edge[i].to; if(v == fa || vis[v])continue;
multi(v, u);
siz[u] += siz[v];
}
}
void solve(int u){
tim++;
mul[u] = 1;
vis[u] = 1;
for(int i = head[u]; ~i; i = edge[i].nex){
int v = edge[i].to; if(vis[v])continue;
top = 0;
multi(v, u);
for(int i = 0; i < top; i++)
{
if(K == (ll)s[i]*(ll)a[u]%(ll)mod)
updata(u, id[i]);
int x = (ll)K * (ll)ni[ (ll)s[i] * (ll)a[u] % (ll)mod ] % (ll)mod;
if(has[x] == tim)
updata(id[i], has_id[x]);
}
for(int i = 0; i < top; i++)
{
add_hash(id[i], s[i]);
}
}
for(int i = head[u];~i;i=edge[i].nex){
int v = edge[i].to; if(vis[v])continue;
siz[0] = siz[v];
solve(find_root(v, u));
}
}
void input(){
init();
for(int i = 1; i <= n; i++)rd(a[i]);
for(int i = 1, u, v; i < n; i++)
{
rd(u); rd(v);
add(u,v); add(v,u);
}
}
int main() {
tim = 0;
memset(has, 0, sizeof has);
for(int i = 0; i < mod; i++) quick(i);
while(rd(n) && rd(K)) {
input();
ans.first = inf;
memset(vis, 0, sizeof vis);
siz[0] = n;
solve(find_root(1,1));
if(ans.first == inf)puts("No solution");
else {
pt(ans.first); putchar(' ');
pt(ans.second); putchar('\n');
}
}
return 0;
}
版权声明:本文博客原创文章。博客,未经同意,不得转载。
HDU 4812 D Tree 树分区+逆+hash新位置的更多相关文章
- hdu 4812 D Tree(树的点分治)
D Tree Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others) Total ...
- HDU 4812 D Tree 树分治+逆元处理
D Tree Problem Description There is a skyscraping tree standing on the playground of Nanjing Unive ...
- HDU 4812 D Tree 树分治
题意: 给出一棵树,每个节点上有个权值.要找到一对字典序最小的点对\((u, v)(u < v)\),使得路径\(u \to v\)上所有节点权值的乘积模\(10^6 + 3\)的值为\(k\) ...
- HDU 3333 - Turing Tree (树状数组+离线处理+哈希+贪心)
题意:给一个数组,每次查询输出区间内不重复数字的和. 这是3xian教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...
- HDU 4812 D Tree
HDU 4812 思路: 点分治 先预处理好1e6 + 3以内到逆元 然后用map 映射以分治点为起点的链的值a 成他的下标 u 然后暴力跑出以分治点儿子为起点的链的值b,然后在map里查找inv[b ...
- HDU - 4812 D Tree 点分治
http://acm.hdu.edu.cn/showproblem.php?pid=4812 题意:有一棵树,每个点有一个权值要求找最小的一对点,路径上的乘积mod1e6+3为k 题解:点分治,挨个把 ...
- HDU 5379 Mahjong tree(树的遍历&组合数学)
本文纯属原创,转载请注明出处.谢谢. http://blog.csdn.net/zip_fan 题目传送门:http://acm.hdu.edu.cn/showproblem.php? pid=537 ...
- HDU 3333 Turing Tree (树状数组)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3333 题意就是询问区间不同数字的和. 比较经典的树状数组应用. //#pragma comment(l ...
- HDU 3333 Turing Tree --树状数组+离线处理
题意:统计一段序列[L,R]的和,重复元素只算一次. 解法:容易看出在线做很难处理重复的情况,干脆全部讲查询读进来,然后将查询根据右端点排个序,然后离散化数据以后就可以操作了. 每次读入一个数,如果这 ...
随机推荐
- cocos2dx怎样设置ios和Android横屏竖屏的几种方法
cocos2d-x编译到ios上.默认是横屏的,若要改为http://竖屏.不同的ios版本号.方法也会不同 在ios7上或许我们设置好了横竖屏.但到了ios6上或许会变化.以下白白给大家分享一下我的 ...
- eclipse 中 Android sdk 无法更新的问题
诶,真是麻烦,想下个东西都下不了. 我也好久没折腾过这个了,在家的电脑是早就下载好了的,然后如今又须要下载一份.下不到.网上搜到了资料,记录下来: 第一种方法: sdk manager - ...
- GMSK调制仿真
GMSK 调制的的原理非常简单. 就是MSK调制前进行Gauss滤波. 在实现中有这样的方法,首先产生高斯系数,对称的上升陂和下降陂系数.输入一个符号,进行上采样,经过高斯滤波器,滤波器的输出做有符号 ...
- HTTPS抓包配置
以Charles为例 配置Charles抓取Https需要手机和PC分别进行配置. 步骤: 1.PC下载charles客户端,并安装. 2.charles客户端安装证书 注意证书安装需要保存在&quo ...
- UNIX网络编程卷1 server编程范式0 迭代server
本文senlie原版的.转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.迭代 TCP server总是在全然处理某个客户的请求后才转向下一个客户. 2.从进程控 ...
- 解决 TortoiseGit 诡异的 Bad file number 问题(转)
问题描述 昨天,以及今天(2014-11-29),使用 TortoiseGit 时碰到了一个诡异的问题. 卸载,清理注册表,重装,重启,各种折腾以后,还是不能解决. 但是23.45分一过,突然灵光一闪 ...
- CSS小记(持续更新......)
1 内联元素和块级元素的区别以及display的三种属性区别 在说起display属性之前,就必须先说说什么是文档流,以及文档流中的内敛元素和块级元素又是指什么? 一直觉得理解了文档流的概念,一堆CS ...
- C#中反射的概念及其使用(转)
提纲:1. 什么是反射2. 命名空间与装配件的关系3. 运行期得到类型信息有什么用4. 如何使用反射获取类型5. 如何根据类型来动态创建对象6. 如何获取方法以及动态调用方法7. 动态创建委托 1.什 ...
- elasticsearch的rest搜索--- 总述
目录: 一.针对这次装B 的解释 二.下载,安装插件elasticsearch-1.7.0 三.索引的mapping 四. 查询 五.对于相关度的大牛的文档 一.针对这次装B 的解释 因为现在又 ...
- Swift中文教程(二)--简单值
原文:Swift中文教程(二)--简单值 Swift使用let关键字声明常量,var关键字声明变量.常量无需在编译时指定,但至少要被赋值一次.也就是说,赋值一次多次使用: var myVariable ...