[GESP202506 六级] 最大因数(含视频)

视频讲解: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; 
}
相关推荐
局部有解1 小时前
Leetcode - 42 接雨水(一维)
数据结构·c++·算法·leetcode
垆边人似月.1 小时前
华为题:矩阵中的最长递增路径
算法·深度优先
小诗懂技术1 小时前
linux驱动中断,相关中断的方式与适用场景
linux·arm开发·驱动开发·算法
不会就选b1 小时前
算法日常・每日刷题--<动态规划>25
算法
Keep_Trying_Go1 小时前
分割算法FastSAM论文详解
深度学习·算法·计算机视觉
星夜离尘561 小时前
MATLAB 5 点滑动平均:filter 与 conv 的输出对齐,以及 2 样本延时的含义
开发语言·算法·matlab·滤波·fir
Dovis(誓平步青云)1 小时前
总用电下降了,为什么家庭能源看板仍然提示异常
java·开发语言·数据库·人工智能·算法·电脑·能源
专注API从业者1 小时前
告别手工盯盘:用 Open‑Claw 搭建电商商品自动化监控与数据分析实战
运维·数据结构·数据挖掘·数据分析·自动化
开开心心就好1 小时前
A3的PDF怎么切成A4?拖一下分割线就行
服务器·开发语言·python·算法·pdf·ocr·tornado