样例输入
5
5 3 2 6 9
样例输出
2 4
表达的意思是在{5,3,2,6,9}这个序列中,3和6这两个数字存在大于1的公因数(3),并且符合i<j的条件
解决方法:在输入一个数字的时候就分解他的质因数,用map来存储,然后在遍历每一个键值对找到其中最小的i和j输出即可。
难点:分解质因数,质因数是表示任何一个数字如果能被分解成除他本身和1相乘的数,那么这个因数一定可以转成质数相乘的形式
比如:6可以表示成 2x3
8可以表示成 2x4 = 2的三次方
12可以表示成 3x4 = 3x2的2次方(12的质因数就是3和2)
以此类推
#include <iostream>
#include <vector>
#include <map>
#include <math.h>
using namespace std;
map<int, vector<int>> st; //st[i]表示i是其质因子的数的集合
int N = 0x3f3f3f3f;
//分解质因数,分解因数
void prime(int x, int index) {
st[x].push_back(index);//注意这里本身也是自己的因数
for (int i = 2; i <= sqrt(x) ; i++) {
if (x % i)
continue;
st[i].push_back(index);//说明i是x的质因子,于是把x下标加入到st[i]中
while (x % i == 0) {
x /= i;
}
if (x > 1)
st[x].push_back(index);//把i这个质因子一直除,剩下的也是x(原数)的质因子,把x(原数)的下标加入到st[x](最后的余数)中
}
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
prime(x, i);
}
pair<int, int> ans = {N, N};
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;
return 0;
}