题目链接
题面
题目大意
给出长度为n的数组,求其中最小公倍数最小的一对数的数组下标。
题目分析
n的范围为 1 ≤ n ≤ 106 ,二重循环遍历数组一定会超时。ai的范围为 1 ≤ n ≤ 107 ,因此可以遍历因子,寻找在数组中出现并为该因子的倍数的最小的两个数,求其最大公倍数。公倍数最小的两个数的对应下标即为答案。出现次数超过两次,其本身可算为最小公倍数,与答案比较。注意中间计算会爆int。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e7;
int vis[10000010],num[1000010];
int main()
{
//clock_t start=clock();
int n,ans1=0,ans2=0;
ll ans=(ll)maxn*(ll)maxn;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&num[i]);
if(vis[num[i]]&&ans>num[i]){
ans=min(ans,(ll)num[i]);
ans1=vis[num[i]];ans2=i;
}
vis[num[i]]=i;
}
for(int i=1;i<=maxn;i++){
int sum=0,bigger=0;
for(int j=i;j<=maxn;j+=i){
if(!vis[j]) continue;
sum++;
if(!bigger){
bigger=j;
}
if(sum==2){
ll another=(ll)bigger*(ll)j/(ll)i;
//cout<<ans<<" "<<another<<endl;
if(another<ans){
ans=another;
ans1=vis[j];
ans2=vis[bigger];
}
//cout<<bigger<<" "<<j<<endl;
break;
}
}
}
printf("%d %d\n",min(ans1,ans2),max(ans1,ans2));
//cout<<clock()-start<<endl;
return 0;
}