求数组中,lcm最小的一对数的下标
可以考虑使用筛法,因为 LCM = a*b / GCD(a,b) 所以,对于任意的一对数来说,如果他们的gcd一样,那么这两个数越小越好。
所以枚举i = gcd,找到最小的两个数gcd(a,b) = i, 求出他们的lcm,然后记录最小值即可。
这里被坑了半天的原因竟然是自己写的lcm。c++17有一个库函数lcm,没有调用自己写的参数是longlong的lcm,同名调用了系统库函数,我传入的值类型是int,然后炸精度了。。。
代码如下
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
long long gcd(long long a,long long b){if (b == 0) return a; return gcd(b , a%b);}
long long lcm(long long a,long long b){ return a/gcd(a,b)*b;}
inline int read(){
int f = 1, x = 0;char ch = getchar();
while (ch > '9' || ch < '0'){if (ch == '-')f = -f;ch = getchar();}
while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
return x * f;
}
const int maxn = 1e7 + 10;
int cnt[maxn];
LL a[1000005];
int main(){
//cout << lcm(3818077,9095777) << endl;
int n = read();
for(int i=0; i<n; i++){
a[i] = read();
cnt[a[i]]++;
}
LL ans = 1e14 + 10;
LL a1 = 0,a2 = 0;
for(int i=1; i<=1e7; i++){
LL p1 = 0,p2 = 0;
LL res = 0;
for(int j=i; j<=1e7; j += i){
if (cnt[j] && p1 == 0){
cnt[j]--;
p1 = j;
}
if (cnt[j] && p2 == 0){
cnt[j]--;
p2 = j;
}
if (p1 && p2) {
res = lcm(p1,p2);
break;
}
}
if (p1) cnt[p1]++;
if (p2) cnt[p2]++;
if (res) {
if (ans > res){
ans = res;
a1 = p1;
a2 = p2;
}
}
}
int ans1 = 0,ans2 = 0;
for(int i=0; i<n; i++){
if (a[i] == a1){
ans1 = i+1;
a1 = 0;
}else if (a[i] == a2){
ans2 = i+1;
a2 = 0;
}
}
cout << min(ans1,ans2) << ' ' << max(ans1,ans2) << endl;
return 0;
}