题意
给出一个长度为$n$的序列$a$,找到一组下标$i,j$,使它们的$lcm(a_i,a_j)$最小。
$zszz,lcm(a_i,a_j)=frac{a_i imes a_j}{gcd(a_i,a_j)}$
考虑枚举下方$gcd$,计算最小的两个是$gcd$倍数的$lcm$。
设$Max=sum_{i=1}^{n}max(a_i)$,计算次数最劣为$sum_{i=1}^{n}lceilfrac{Max}{i} ceil$,为调和级数。
$1.8 imes 10^{8}$左右,$4s$能过。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxm=1e6+5,maxn=1e7+5;
int n,a[maxm],mapp[maxn],Max,pos1,pos2;
ll ans=1e18;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i]),mapp[a[i]]++,Max=max(Max,a[i]);
for(int i=1;i<=n&&i<=ans;++i) {
if(mapp[i]>1&&ans>i) {
pos1=pos2=i;
ans=i;
}
int js=0;
ll wz=0;
for(int j=1;i*j<=Max;++j) {
if(mapp[i*j]) {
if(js||mapp[i*j]>1) {
if(js) {
ll temp=wz*i*j;
if(temp<ans) {
pos1=wz*i,pos2=i*j;
ans=temp;
}
}
break;
}
else js++,wz=j;
}
}
}
if(pos1==pos2) {
int js=0;
for(int i=1;i<=n&&js<=1;++i) if(a[i]==pos1) printf("%d ",i);
putchar('
');
}
else {
for(int i=1;i<=n;++i) if(a[i]==pos1) {pos1=i;break;}
for(int i=1;i<=n;++i) if(a[i]==pos2) {pos2=i;break;}
if(pos1>pos2) swap(pos1,pos2);
printf("%d %d
",pos1,pos2);
}
return 0;
}