问题描述
给定 n 个正整数 Ai,请找出两个数 i,j 使得 i<j 且 Ai 和 Aj 存在大于 1 的公因数。
如果存在多组 i,j请输出 ii 最小的那组。如果仍然存在多组 i,j请输出 i最小的所有方案中 j 最小的那组。
输入格式
输入的第一行包含一个整数 n。
第二行包含 n 个整数分别表示 A1,A2,……,An,相邻整数之间使用一个空格分隔。
输出格式
输出一行包含两个整数分别表示题目要求的 i,j用一个空格分隔。
暴力:
函数__gcd(),双层for循环,保证i<j;遇到第一个就return 0;
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n;
int nums[N];
int main(){
cin >> n;
for(int i = 1 ;i <= n; i++) cin >> nums[i];
for(int i = 1; i <= n-1; i++){
for(int j = i+1; j <= n; j++){
if(__gcd(nums[i], nums[j]) > 1){
cout << i << " " << j << endl;
return 0;//直接结束程序运行
}
}
}
return 0;
}
AC:
我们可以写一个分解质因数的算法,并且定义一个map容器,前面存质因数,后面存数组的角标,然后用for循环保证数组角标是由小到大即可。
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
map<int,vector<int>>st;//前面是质因数,后面是角标数组
int n=0;
int nums[501000];
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> nums[i];
for (int i = 1; i <= n; i++)//找公因数,角标存入
{
for (int j = 2; j <= nums[i] / j; j++)//一个数的质因数不会超过他的平方根
if (nums[i] % j == 0)
{
st[j].push_back(i);
while (nums[i] % j == 0) {//保证公因数都是质数
nums[i] /= j;
}
}
if (nums[i] > 1)//本身就是一个质因数
st[nums[i]].push_back(i);
}
pair<int, int>ans = {100000000,100000000};
for (auto [x,y] : st) {
if (y.size() < 2)
continue;
if (y[0] < ans.first) {
ans = { y[0], y[1] };
}
else if (y[0] == ans.first) {
if (y[1] < ans.second) {
ans = { y[0], y[1] };
}
}
}
cout << ans.first << " " << ans.second << endl;
}
这里稍微说一个分解质因数的算法,先传入一个数X,然后令i=2,进行质因数循环判断,如果取余运算等于0,那么这个i就是这个质因数,再写一个while循环让他一直分解,直到没有位置,最后如果大于一,那么他本身就是一个质数。循环的终止条件是一个数的质因数不会超过他的平方根。
还有这个auto的用法,如果auto后加&符号,我们可以修改遍历的对象,如果不加就不能修改。但是加了之后会影响代码运行的效率