传送门
题意:求个数中最小公倍数数值最小的两个数的下标。
参考博客:https://blog.csdn.net/qq_41157137/article/details/89353527
思路:
对于包含 的数
如果 是
的最大公约数,那么
一定小于
,后面就可以不用考虑了
如果不是
不是
的最共公约数( 满足
是
的因子,比如
)。那么
也一定小于
,如果
是
的最大公约数,同样
,后面就可以不用考虑了
所以我们只需要得到每个d的倍数的前2项即可,时间复杂度(1e7*log(le7))
代码:
///#include <bits/stdc++.h>
///#include <unordered_map>
///#include <unordered_set>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <map>
#include <new>
#include <ctime>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai = acos(-1.0);
const double E = exp(1.0);
const int INF = 0x3f3f3f3f;
const long long mod = 1e9 + 7;
int n, maxn, p1, p2, lcm[10000005], num[10000005];
ll ans_lcm = 1e18 + 7;
bool vis[10000005];
int main() {
maxn = 0;
memset(vis, false, sizeof(vis));
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &num[i]);
maxn = max(maxn, num[i]);
///存在相同数字的情况
if (vis[num[i]]) {
if (ans_lcm > num[i]) {
ans_lcm = num[i];
p1 = i;
p2 = lcm[num[i]];
}
} else
vis[num[i]] = 1, lcm[num[i]] = i;
}
for (int i = 1; i <= maxn; i++) {///枚举公因子
int pre = -1;
for (int j = i; j <= maxn; j+=i) {///枚举数字
if (vis[j] && pre == -1) {
pre = j;
} else if (vis[j] && pre != -1) {
ll now_lcm = (ll) pre / __gcd(pre, j) * j;
if (ans_lcm > now_lcm) {
ans_lcm = now_lcm;
p1 = lcm[pre];
p2 = lcm[j];
}
break;
}
}
}
printf("%d %d\n", min(p1, p2), max(p1, p2));
return 0;
}