P13016 [GESP202506 六级] 最大因数
题目描述
给定一棵有 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。
解析
要想求两个节点的最近距离,就要找到他们俩的共同祖先,详见代码:
#include <bits/stdc++.h>
using namespace std;
int q,x,y;
int f(int a){//求最大因子
for(int i=2;i*i<=a;i++){
if (a%i==0){
return a/i;
}
}
return 1;
}
int main(){
cin>>q;
while(q--){
cin>>x>>y;
int cnt=0;//距离
while(x!=y){//不相等,即没到共同根
if (x>y){//谁大,就求谁的父节点
x=f(x);
}else{
y=f(y);
}
cnt++;//距离增加1
}
cout<<cnt<<"\n";
}
return 0;
}
加上记忆化,会更快些,其实没什么用
#include <bits/stdc++.h>
using namespace std;
int q,x,y;
map <int,int> mp;
int f(int a){//求最大因子
if (mp[a]>0) return mp[a];
for(int i=2;i*i<=a;i++){
if (a%i==0){
mp[a]=a/i;
return mp[a];
}
}
return mp[a]=1;
}
int main(){
cin>>q;
while(q--){
cin>>x>>y;
int cnt=0;//距离
while(x!=y){//不相等,即没到共同根
if (x>y){//谁大,就求谁的父节点
x=f(x);
}else{
y=f(y);
}
cnt++;//距离增加1
}
cout<<cnt<<"\n";
}
return 0;
}