D树

时间限制:10000/5000 MS(Java / Others)内存限制:102400/102400 K(Java / Others)
总共提交5400个已接受的提交1144

问题描述
南京理工大学的操场上站着一棵高大的树。在树的每个分支上是一个整数(树可以被看作是一个有N个顶点的连通图,而每个分支可以被当作一个顶点)。今天,树下的学生正在考虑一个问题:我们可以在树上找到这样一个链,使链上所有整数(mod 10 6 + 3)的乘积等于K?
你能帮助他们解决这个问题吗?
输入
有几个测试用例,请处理,直到EOF。
每个测试用例都以包含两个整数N(1 <= N <= 10 5)和K(0 <= <<10 6 + 3)的行开始。下面一行包含n个数字v i(1 <= v i <10 6 + 3),其中vi表示顶点i上的整数。然后遵循N - 1行。每行包含两个整数x和y,表示顶点x和顶点y之间的无向边。
产量
对于每个测试用例,打印一个单行,其中包含两个整数a和b(其中a <b),表示链的两个端点。如果存在多个解决方案,请打印词典上最小的一个。如果没有解决方案,请打印“无解”(不含引号)。
欲了解更多信息,请参阅下面的示例输出。
示例输入
5 60 2 5 2 3 3 1 2 1 3 2 4 2 5 5 2 2 5 2 3 3 1 2 1 3 2 4 2 5
示例输出
3 4 没有解决方案

暗示

1.“请按字典顺序打印最小的一个”。是指:先按照第一个数字的大小进行比较,若第一个数字大小相同,则按照第二个数字大小进行比较,依次类别。 2.若出现栈溢出,推荐使用C ++语言提交,并通过以下方式扩栈: #pragma comment(linker,“/ STACK:102400000,102400000”)

点分治

这种树上找路径问题最容易想到的就是点分治

点治的思想其实很简单,分别以每个点为根,找出所有经过根的路径更新答案

由于路径是一个二维的量,直接枚举是O(n^2),而点分治通过固定一个根而使问题简化为一维O(n)

而由于树的性质,只要我们每次求出重心就可以保证最多只有logn层

总的复杂度就成了O(每一层操作复杂度 * logn)一般都是O(nlogn)或O(nlog^2n)

然而我点分治还是很生疏【我还是太弱了】

对于这道题,我们需要找到两条路径权值乘积取模为K

对于x * y ≡ K (mod P),可以化为x ≡ K/y (mod P)

所以我们只需开一个hash表存x的值,对于每个y,用K乘上y的逆元查表更新答案就好了

要注意的细节就是根节点也要算上,而且查找与更新的路径只能有一个经过根,也就是算y时不算上,而算x存表时算上根

继续练习吧

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 100005,maxm = 200005,INF = 1000000000;
const LL P = 1000003;
inline int RD(){int out = 0,flag = 1; char c = getchar();while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}return out * flag;
}
int N,K,V[maxn],Siz[maxn],F[maxn],vis[maxn],rt,sum,ansx,ansy;
LL Hash[P],tmp[maxn],d[maxn],id[maxn],inv[P],cnt = 0;
int head[maxn],nedge = 0;
struct EDGE{int to,next;}edge[maxm];
inline void build(int u,int v){edge[nedge] = (EDGE){v,head[u]}; head[u] = nedge++;edge[nedge] = (EDGE){u,head[v]}; head[v] = nedge++;
}
void getRT(int u,int fa){int to; Siz[u] = 1; F[u] = 0;Redge(u) if (!vis[to = edge[k].to] && to != fa){getRT(to,u);Siz[u] += Siz[to];F[u] = max(F[u],Siz[to]);}F[u] = max(F[u],sum - Siz[u]);if (F[u] < F[rt]) rt = u;
}
inline void query(int x,int u){x = 1ll * inv[x] * K % P;int v = Hash[x];if (!v) return;if (v < u) swap(u,v);if (u < ansx || (u == ansx && v < ansy))ansx = u,ansy = v;
}
void dfs(int u,int fa){tmp[++cnt] = d[u]; id[cnt] = u; int to;Redge(u) if (!vis[to = edge[k].to] && to != fa){d[to] = 1ll * V[to] * d[u] % P;dfs(to,u);}
}
void solve(int u){int to; vis[u] = true; Hash[V[u]] = u;Redge(u) if (!vis[to = edge[k].to]){cnt = 0; d[to] = V[to];dfs(to,u);REP(i,cnt) query(tmp[i],id[i]);cnt = 0; d[to] = 1ll * V[to] * V[u] % P;dfs(to,u);REP(i,cnt) if (!Hash[tmp[i]] || Hash[tmp[i]] > id[i]) Hash[tmp[i]] = id[i];}Hash[V[u]] = 0;Redge(u) if (!vis[to = edge[k].to]){cnt = 0; d[to] = 1ll * V[to] * V[u] % P;dfs(to,u);REP(i,cnt) Hash[tmp[i]] = 0;}Redge(u) if (!vis[to = edge[k].to]){sum = Siz[to]; F[rt = 0] = INF;getRT(to,rt);solve(rt);}
}
void init(){memset(vis,0,sizeof(vis));memset(head,-1,sizeof(head)); nedge = 0; ansx = ansy = INF;REP(i,N) V[i] = RD() % P;REP(i,N - 1) build(RD(),RD());
}
void INIT(){inv[1] = 1;for (int i = 2; i < P; i++){inv[i] = ((P - P / i) * inv[P % i] % P + P) % P;}
}
int main(){INIT();while (~scanf("%d%d",&N,&K)){init();F[rt = 0] = INF; sum = N;getRT(1,rt);solve(rt);if (ansx == INF) printf("No solution\n");else printf("%d %d\n",ansx,ansy);}return 0;
}

转载于:https://www.cnblogs.com/Mychael/p/8282789.html

HDU4812 D tree 【点分治 + 乘法逆元】相关推荐

  1. 点分治问题 ----------- HDU4812 D Tree [点分治 + 乘法逆元]

    题目链接 题目大意: 给你一颗树,树上节点有个权值aia_iai​,现在问你这颗树上是否存在一条路径这个路径上面权值的乘积模1e6+3等于k. 如果有多组答案输出字典序最小的答案 解题思路: 1.首先 ...

  2. 【CF#715C】Digit Tree 点分治+乘法逆元

    AC通道:http://codeforces.com/problemset/problem/715/C [题目大意] 给定一个有N个点的树,问其中有多少条路径满足他们的边权连成的数对M取余为0. 其中 ...

  3. luogu P5142 区间方差(线段树、乘法逆元)

    luogu P5142 区间方差 本题要求维护模区间方差,很明显是一道数据结构题. 我们化简方差公式: 而平均数等于 可以发现,我们只需要维护序列的区间和和区间平方和,就可以维护平均数和方差. 区间和 ...

  4. P5431 【模板】乘法逆元2(小学数学题,毒瘤鱼,卡常之王yyds)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 P5431 [模板]乘法逆元2 题目传送门 题目大意: 给定 nnn 个正整数 aia_iai​ ,求 ...

  5. luogu P2613 【模板】有理数取余(费马小定理,乘法逆元)

    整理的算法模板合集: ACM模板 目录 题目传送门 题目传送门 相当于是一个高精的费马小定理求乘法逆元.虽然数据达到了101000110^{10001}1010001,但是我们可以使用快读然后一直模m ...

  6. 洛谷——P3811 【模板】乘法逆元

    P3811 [模板]乘法逆元 线性求逆元 逆元定义:若$a*x\equiv1 (\bmod {b})$,且$a$与$b$互质,那么我们就能定义: $x$为$a$的逆元,记为$a^{-1}$,所以我们也 ...

  7. 【luogu 3811】【模板】乘法逆元

    题目背景 这是一道模板题 题目描述 给定n,p求1~n中所有整数在模p意义下的乘法逆元. 输入输出格式 输入格式: 一行n,p 输出格式: n行,第i行表示i在模p意义下的逆元. 输入输出样例 输入样 ...

  8. 51nod 1256 乘法逆元(扩展欧几里得)

    问题: 给出2个数M和N(M < N),且M与N互质,找出一个数K满足0 < K < N且K * M % N = 1,如果有多个满足条件的,输出最小的. Input 输入2个数M, ...

  9. 乘法逆元通俗易懂的理解方法

    最近,发现数论真的很重要,基本上一套题必出一个数论的题.故接下来,要好好的看一看数论了. 乘法逆元我觉得其本质:就是数论里的倒数. 由上图你会发现:其取模的运算不满足除法的分配律,那么如何求除法的模运 ...

  10. 求乘法逆元的几种方法

    (数学渣,下面的文字可能有误,欢迎指教) 乘法逆元的定义貌似是基于群给出的,比较简单地理解,可以说是倒数的概念的推广.记a的关于模p的逆元为a^-1,则a^-1满足aa^-1≡ 1(mod p) 加减 ...

最新文章

  1. Oracle 冷备份
  2. java的同步关键字_简单了解Java synchronized关键字同步
  3. mysql handler socket_MySQL的NoSQL插件HandlerSocket
  4. 广义相对论与量子力学的矛盾
  5. 入门Web前端有哪些误区?该如何避免?
  6. 部署redis mysql_【服务器部署Redis、Mysql等】-解决方式
  7. matlab自定义窗口名
  8. jq查找字段忽略html标签,jQuery过滤HTML标签并高亮显示关键字的方法
  9. IIS内部服务错误aspx与asp
  10. 因离职,3人拟终止人才项目!
  11. 异构计算助力客户春节webp图片编码
  12. JVM史上最佳入门指南
  13. 微软破常规发LNK漏洞补丁 金山卫士完美修复
  14. CCFTF17(上海):认知计算产业化如何落地(知识图谱、智能问答等)
  15. 【数据结构笔记】Leetcode:718. 最长重复子数组(动态规划)
  16. 苹果mac装双系统对电脑有影响吗?Mac电脑装双系统的利与弊
  17. Tomcat:Tomcat网站上的core和deployer的区别
  18. PHP对接美团配送接口遇到的问题
  19. Project2 分段切割路面,只取一个种子点
  20. 如果更好的做好MES系统运维

热门文章

  1. 在线制作车牌效果图_价格低的防火板材行业专家在线为您服务
  2. NSMethodSignature, NSInvocation源码分析
  3. Softmax分类函数
  4. css固定姓名显示长度,排列更整齐
  5. UVALive 6508 Permutation Graphs
  6. 关于PPP认证中的PAP和CHAP原理取证与相关疑问
  7. 【实习记】2014-09-26恢复linux下误删的ntfs盘中的文件
  8. C# 退出应用程序的几种方法(待测试)
  9. 多种方法让网络共享资源自动映射
  10. jquery发送ajax请求返回数据格式