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]的和,重复元素只算一次. 解法:容易看出在线做很难处理重复的情况,干脆全部讲查询读进来,然后将查询根据右端点排个序,然后离散化数据以后就可以操作了. 每次读入一个数,如果这 ...
随机推荐
- iOS_21团购_发送请求【点评】数据
结果表明,一个简单的请求: 用到的点评封装的类: 使用tableView简单展示: // // DealListController.m // 帅哥_团购 // // Created by beyon ...
- Oracle cloud control 12c 的启动与关闭
Oracle cloud control 12c整个安装比較复杂,光是安装路径的选择,登录password,端口号等众多个配置不免让人眼花缭乱,目不暇接.本文描写叙述的是安装完成后怎样获取安装时设定的 ...
- 轻狂写的桌面日历秀NSIS脚本供大家参考学习
原文 轻狂写的桌面日历秀NSIS脚本供大家参考学习 现在共享桌面日历秀的NSIS脚本,以便交流学习.此脚本实现的功能如下: 7-Zip打开看不到内容.自动读取原安装路径,如果有则不允许更改.取得编译日 ...
- M、V、C
概述 Model-View-Controller(MVC),即模型-视图-控制器. MVC将软件系统分成三大部分:Model,View,Controller,三个部分通过某种机制通信 M.V.C的职能 ...
- Flux是一个Facebook团队的前端开发架构
Flux是一个Facebook团队的前端开发架构 Flux introduction 本文组成: React 官方文档翻译 相关实践心得. 内容上是Flux的介绍,例子将会在以后写出.一旦稍微多了解一 ...
- Android Bitmap OutOfMemory 解决的方法
在Android应用里,最耗费内存的就是图片资源.并且在Android系统中.读取位图Bitmap时,分给虚拟机中的图片的堆栈大小仅仅有8M.假设超出了.就会出现OutOfMemory异常 E/And ...
- Yeoman generators 创建 ASP.NET 应用程序
Yeoman generators 创建 ASP.NET 应用程序 上一篇:<Windows 搭建 .NET 跨平台环境并运行应用程序> 阅读目录: Install Node.js Ins ...
- 使用 Eclipse 的 SVN 主要插件创建项目/支/标签
原文 阅读 Mark Phippard 该博客以及<Subversion 与版本号控制>之后,我了解到 分支/标签 是 SVN 非常棒的特性之中的一个.但我在使用推荐的 "tru ...
- 仅当使用了列的列表,并且 IDENTITY_INSERT 为 ON 时,才能在表中为标识列指定显式值问题
今天在处理数据库过程中碰到这样的问题在插入一条数据到表中 系统报这样的错误 仅当使用了列的列表,并且 IDENTITY_INSERT 为 ON 时,才能在表中为标识列指定显式值问题 表有一列是自增长的 ...
- JS编程
JS编程常识 一.UI层的松耦合 松耦合就是要求各层遵循“最少知识原则”,或者说是各层各司其职,不要越权: HTML:结构层 CSS:表现层 JS:行为层 对于各层的职能,有一句比较贴切的解释:H ...