意甲冠军:

特定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. 024找到二维阵列(keep it up)

    剑指offer在标题中:http://ac.jobdu.com/problem.php? pid=1384 题目描写叙述: 在一个二维数组中,每一行都依照从左到右递增的顺序排序.每一列都依照从上到下递 ...

  2. NSIS:简单按钮美化插件SkinButton,支持透明PNG图片。

    原文 NSIS:简单按钮美化插件SkinButton,支持透明PNG图片. 征得作者贾可的同意,特发布按钮美化插件SkinButton. 插件说明: 使用GDI+库写的一个简单按钮美化插件,支持透明P ...

  3. Android定调的发展

    首先,介绍一下Android系统支持的铃声格式. 有下面几种: 64赫兹Midi,AAC.AAC+.AMR.WAV.MP3.Real Audio.WMA.OGG等格式. 将音频文件设置成铃声非常eas ...

  4. Hystrix提高系统可用性

    使用Hystrix提高系统可用性 今天稍微复杂点的互联网应用,服务端基本都是分布式的,大量的服务支撑起整个系统,服务之间也难免有大量的依赖关系,依赖都是通过网络连接起来. (图片来源:https:// ...

  5. ABP应用层——权限验证

    ABP应用层——权限验证 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ABP的官方网站:http://www.aspnetboilerpla ...

  6. 易Android登录Demo

    上一页介绍Android项目简单的页面跳转实例,算是对开发环境的熟悉,这一篇将在此基础上增加一些简单的逻辑,实现登录的效果. 登录之前: 登录成功: watermark/2/text/aHR0cDov ...

  7. zoj3791(An Easy Game) DP

    意甲冠军:给定两个01弦s1,s2.每一个变化s1在m字 - 位.要求k制作步骤之后s1变s2有多少种方法. 解法:DP,关键是状态的设计.考虑还是唯一性和可传递性.dp[i][j]表示第i步后有j个 ...

  8. CodeIgniter入门——HelloWorld

    原文:CodeIgniter入门--HelloWorld CodeIgniter(CI)是一套给PHP网站开发者使用的应用程序开发框架和工具包. 初次接触,来一个HelloWorld~~~ ^_^ 准 ...

  9. ArcEngine下一个TIN生成的轮廓

    太晚了,直接连接的源代码: /// <summary> /// TIN生成等高线 /// </summary> /// <param name="pInterv ...

  10. js中,(function(){})()的用法解析

    (function($){...})(jQuery)  含义 经常用,今天总结一下,下文摘自某网友的总结: (function($){...})(jQuery)实际上是匿名函数,不懂得朋友可以继续往下 ...