题目:
CodeForces - 1154G:Minimum Possible LCM
题意:
从n个数中选出2个数,使得这两个数的最小公倍数最小
分析:
LCM(a,b) = a * b / gcd(a,b);考虑枚举公因数d,假设n个数中具有因子d的数分别是x1,x2,x3,x4.....(x1 < x2 < x3 < x4 ......)
如果x1 与 x2 的最大公因数就是d,那么lcm(x1,x2) = x1*x2/d,如果x4 与 x1 的最大公因数也是d,那么x4*x1/d一定大于x1*x2/d,所以后面的就不用考虑了
如果x1 与x2 的最大公因数不是d,那么lcm(x1,x2) 一定小于x1*x2/d,即使x4 与 x1的最大公因数是d,那么x4*x1/d一定大于lcm(x1,x2),同样后面也不用考虑了
所以我们只需要得到每个d的倍数的前2项即可,时间复杂度(1e7*log(le7))
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e7+17;
int a[maxn],pos[maxn],n,v,x,y;
int main(){
cin >> n; long long res = 1e18;
for(int i = 1;i <= n ; ++i){
cin >> v;
a[v]++;
if(a[v] > 1 && v < res){ //处理相同的数
res = v;
x = pos[v];
y = i;
}
pos[v] = i;
}
for(int i = 1;i < maxn; ++i){
int val = 0;
for(int j = i;j < maxn; j+=i){
if(!a[j]) continue;
if(!val) val = j;
else{
long long g = __gcd(val/i,j/i);
if(g == 1){
long long lcm = 1LL*j/i*val;
if(lcm < res){
res = lcm;
x = pos[val];
y = pos[j];
}
}
break;
}
}
}
if(x > y) swap(x,y);
cout << x << " " << y << '\n';
return 0;
}