2025年6月GESP(C++六级):最大因数
2025年6月GESP(C++六级):最大因数
题目描述
给定一棵有 10910^9109 个结点的有根树,这些结点依次以 1,2,…,1091, 2, \dots, 10^91,2,…,109 编号,根结点的编号为 111。对于编号为 kkk(2≤k≤1092 \leq k \leq 10^92≤k≤109)的结点,其父结点的编号为 kkk 的因数中除 kkk 以外最大的因数。
现在有 qqq 组询问,第 iii(1≤i≤q1 \leq i \leq q1≤i≤q)组询问给定 xi,yix_i, y_ixi,yi,请你求出编号分别为 xi,yix_i, y_ixi,yi 的两个结点在这棵树上的距离。两个结点之间的距离是连接这两个结点的简单路径所包含的边数。
输入格式
第一行,一个正整数 qqq,表示询问组数。
接下来 qqq 行,每行两个正整数 xi,yix_i, y_ixi,yi,表示询问结点的编号。
输出格式
输出共 qqq 行,每行一个整数,表示结点 xi,yix_i, y_ixi,yi 之间的距离。
输入输出样例 #1
输入 #1
3
1 3
2 5
4 8
输出 #1
1
2
1
输入输出样例 #2
输入 #2
1
120 650
输出 #2
9
说明/提示
对于 60%60\%60% 的测试点,保证 1≤xi,yi≤10001 \leq x_i, y_i \leq 10001≤xi,yi≤1000。
对于所有测试点,保证 1≤q≤10001 \leq q \leq 10001≤q≤1000,1≤xi,yi≤1091 \leq x_i, y_i \leq 10^91≤xi,yi≤109。
题目分析
本题要求计算一棵特殊树中两个节点之间的距离。树的结构如下:
- 根节点为1
- 对于节点k(k ≥ 2),其父节点是k的最大真因数(即除k本身外的最大因数)
解题思路
- 父节点计算:对于节点x,其父节点是x的最大真因数。通过从2开始枚举到√x,找到x的最小质因数i,则x/i即为最大真因数。若未找到(x为质数),则父节点为1。
- 距离计算:两个节点x、y之间的距离通过以下步骤计算:
- 不断将x和y中较大的节点上移至其父节点,直到两者相遇
- 每次移动计数一次,总移动次数即为两节点间的距离
AC代码
#include <bits/stdc++.h>
using namespace std;int q;// 计算节点x的父节点(最大真因数)
int fa(int x) {// 从2枚举到√xfor (int i = 2; i * i <= x; i++) {if (x % i == 0) return x / i; // 找到最小质因数i,返回最大真因数x/i}// 未找到因数(x为质数),返回1return 1;
}// 计算两个节点x,y在树上的距离
int lca(int x, int y) {int ans = 0;// 当x和y不相同时循环while (x != y) {// 移动较大的节点(因为树中父节点小于子节点)if (x < y) y = fa(y); // 移动yelse x = fa(x); // 移动xans++; // 增加移动计数}return ans; // 返回总移动次数(即距离)
}int main() {cin >> q;while (q--) {int x, y;cin >> x >> y;cout << lca(x, y) << endl;}return 0;
}
代码功能解析
- fa(int x):
- 功能:计算节点x的父节点
- 实现:通过试除法找到x的最小质因数,返回对应的最大真因数
- lca(int x, int y):
- 功能:计算两节点间距离
- 实现:循环比较节点大小,较大者上移父节点,直到相遇,返回移动次数
- 主程序:
- 读取询问次数q
- 对每组询问,读取节点对(x,y),输出距离计算结果
文末彩蛋:
点击查看老师的个人主页,学习csp信奥赛完整系列课程:
https://edu.csdn.net/lecturer/7901