视频讲解:GESP202506 六级 最大因数-信息学奥赛GESP等级考试真题解析
一、原题
题目描述
给定一棵有 10^9 个结点的有根树,这些结点依次以 1,2,...,10^9 编号,根结点的编号为 1。对于编号为 k(2≤k≤10^9)的结点,其父结点的编号为 k 的因数中除 k 以外最大的因数。
现在有 q 组询问,第 i(1≤i≤q)组询问给定 xi,yi,请你求出编号分别为 xi,yi 的两个结点在这棵树上的距离。两个结点之间的距离是连接这两个结点的简单路径所包含的边数。
输入格式
第一行,一个正整数 q,表示询问组数。
接下来 q 行,每行两个正整数 xi,yi,表示询问结点的编号。
输出格式
输出共 q 行,每行一个整数,表示结点 xi,yi 之间的距离。
输入输出样例
输入 #1
3
1 3
2 5
4 8
输出 #1
1
2
1
输入 #2
1
120 650
输出 #2
9
说明/提示
对于 60% 的测试点,保证 1≤xi,yi≤1000。
对于所有测试点,保证 1≤q≤1000,1≤xi,yi≤10^9。
二、做题思路
1)填充数据

cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
//1)填充数据
//1.1)确定组数q
int q;cin>>q;
//1.2)填充q组询问编号
for(int i=1;i<=q;i++){
int x,y;
cin>>x>>y;
}
return 0;
}
2)标记所有最大因数,以及位置

cpp
#include<bits/stdc++.h>
using namespace std;
void cal(int x){
//2.2)标记当前数字
int now=0;
dict[x].push_back(now);
if(x==1) return ;//1标记后直接退出
//2.3)寻找当前最小因数,同时记录出现位置
for(int i=2;i*i<=x;i++){
//16(8) 8(4) 4(2) 2(1) 1
while(x%i==0&&x!=i){
//2.4)标记对应的大因数的出现位置
x/=i;
now++;
dict[x].push_back(now);
}
}
//2.5)1也需要标记
now++;
dict[1].push_back(now);
}
int main(){
//1)填充数据
//1.1)确定组数q
int q;cin>>q;
//1.2)填充q组询问编号
for(int i=1;i<=q;i++){
int x,y;
cin>>x>>y;
//2.1)清除上一次,函数开始计算
dict.clear();
cal(x),cal(y);
}
return 0;
}
3)找标记2次的最大值,输出结果

cpp
#include<bits/stdc++.h>
using namespace std;
map<int,vector<int>>dict;
void cal(int x){
/....
}
int main(){
//1)填充数据
//1.1)确定组数q
int q;cin>>q;
//1.2)填充q组询问编号
for(int i=1;i<=q;i++){
int x,y;
cin>>x>>y;
//2)标记所有最大因数,以及位置
//...
//3)找标记2次的最大值
int ans=INT_MAX;
for(auto it:dict){
if(it.second.size()==2){
ans=min(ans,it.second[0]+it.second[1]);
}
}
//4)输出结果
cout<<ans<<endl;
}
return 0;
}
三、答案
cpp
#include<bits/stdc++.h>
using namespace std;
void cal(int x){
//2.2)标记当前数字
int now=0;
dict[x].push_back(now);
if(x==1) return ;//1标记后直接退出
//2.3)寻找当前最小因数,同时记录出现位置
for(int i=2;i*i<=x;i++){
//16(8) 8(4) 4(2) 2(1) 1
while(x%i==0&&x!=i){
//2.4)标记对应的大因数的出现位置
x/=i;
now++;
dict[x].push_back(now);
}
}
//2.5)1也需要标记
now++;
dict[1].push_back(now);
}
int main(){
//1)填充数据
//1.1)确定组数q
int q;cin>>q;
//1.2)填充q组询问编号
for(int i=1;i<=q;i++){
int x,y;
cin>>x>>y;
//2.1)清除上一次,函数开始计算
dict.clear();
cal(x),cal(y);
}
return 0;
}