意甲冠军:

特定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新位置的更多相关文章

  1. hdu 4812 D Tree(树的点分治)

    D Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total ...

  2. HDU 4812 D Tree 树分治+逆元处理

    D Tree Problem Description   There is a skyscraping tree standing on the playground of Nanjing Unive ...

  3. HDU 4812 D Tree 树分治

    题意: 给出一棵树,每个节点上有个权值.要找到一对字典序最小的点对\((u, v)(u < v)\),使得路径\(u \to v\)上所有节点权值的乘积模\(10^6 + 3\)的值为\(k\) ...

  4. HDU 3333 - Turing Tree (树状数组+离线处理+哈希+贪心)

    题意:给一个数组,每次查询输出区间内不重复数字的和. 这是3xian教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...

  5. HDU 4812 D Tree

    HDU 4812 思路: 点分治 先预处理好1e6 + 3以内到逆元 然后用map 映射以分治点为起点的链的值a 成他的下标 u 然后暴力跑出以分治点儿子为起点的链的值b,然后在map里查找inv[b ...

  6. HDU - 4812 D Tree 点分治

    http://acm.hdu.edu.cn/showproblem.php?pid=4812 题意:有一棵树,每个点有一个权值要求找最小的一对点,路径上的乘积mod1e6+3为k 题解:点分治,挨个把 ...

  7. HDU 5379 Mahjong tree(树的遍历&amp;组合数学)

    本文纯属原创,转载请注明出处.谢谢. http://blog.csdn.net/zip_fan 题目传送门:http://acm.hdu.edu.cn/showproblem.php? pid=537 ...

  8. HDU 3333 Turing Tree (树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3333 题意就是询问区间不同数字的和. 比较经典的树状数组应用. //#pragma comment(l ...

  9. HDU 3333 Turing Tree --树状数组+离线处理

    题意:统计一段序列[L,R]的和,重复元素只算一次. 解法:容易看出在线做很难处理重复的情况,干脆全部讲查询读进来,然后将查询根据右端点排个序,然后离散化数据以后就可以操作了. 每次读入一个数,如果这 ...

随机推荐

  1. Oracle 数据库 JOB 失败后解密法重试

    因为官方文档上没有找到相关的说明,所以这里进行了例如以下測试,为了找到oracle数据库中 job 失败后重试时间的规律. 数据库版本号:11.2.0.3 測试说明:这里创建了一个日志表以及一个执行时 ...

  2. 十天学Linux内核之第七天---电源开和关时都发生了什么

    原文:十天学Linux内核之第七天---电源开和关时都发生了什么 说实话感觉自己快写不下去了,其一是有些勉强跟不上来,其二是感觉自己越写越差,刚开始可能是新鲜感以及很多读者的鼓励,现在就是想快点完成自 ...

  3. aul 学习测试(测量)

    -------------------aul5 ----------test0------------------------- select file#,rfile#,name from v$dat ...

  4. hdu Oulipo(kmp)

    Problem Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, w ...

  5. ABP领域层——实体

    ABP领域层——实体 基于DDD的现代ASP.NET开发框架--ABP系列之10.ABP领域层——实体 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的 ...

  6. SSIS从理论到实战,再到应用(4)----流程控制之For循环

    原文:SSIS从理论到实战,再到应用(4)----流程控制之For循环 上期回顾: SSIS从理论到实战,再到应用(3)----SSIS包的变量,约束,常用容器 在SSIS体系中,控制流可能经常会遇到 ...

  7. 网络资源(6) - EJB视频

    2014_08_24 http://v.youku.com/v_show/id_XMjE0NjE3MDA0.html?f=5227828 01_EJB3.0_下载安装与运行jboss -------- ...

  8. sql server判断表是否存在

    1.判断数据表是否存在 方法一: use yourdb;go if object_id(N'tablename',N'U') is not nullprint '存在'else print '不存在' ...

  9. NYOJ 330 一个简单的数学

    一个简单的数学题 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描写叙述 zyc近期迷上了数学,一天,dj想出了一道数学题来难住他.算出1/n,但zyc一时答不上来希望大家能 ...

  10. oracle_彻底删除oracle

    例如ORACLE安装路径为:C:\ORACLE 实现方法: 1. 开始->设置->控制面板->管理工具->服务 停止所有Oracle服务. 2. 开始->程序->O ...