题意
给出一个长度为$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; }