题目链接:
http://codeforces.com/contest/1154/problem/G
题意:
有n个数,每个数的值为$a_i$
找到一个最小的$lcm(a_i, a_j)$并且满足$1 \le i < j \le n$
数据范围:
$2 \le n \le 10^6$
$1 \le a_i \le 10^7$
分析:
错误想法1,用每个$a_i$去找倍数,然后找到最小的数,它是两个数的倍数。错在最小公倍数可能很大。这样枚举会超时。
错误想法2,分解每个$a_i$,在每个因数里面找最小的两个数。同样,因为复杂度为$O\left ( m^{3/2} \right )$,超时
正确解法:枚举$x$从1到$m$作为因数,遍历1到m的所有$x$的倍数。如果存在两个数都是$x$的倍数,那么最小的两个数可以取得最大公因数为$x$的最小公倍数
ac代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=1e6+10; const int maxm=1e7+10; int pos[maxm]; ll ans=1e18; int ansl,ansr; vector<int>ve; int main() { int n; scanf("%d",&n); for(int i=1; i<=n; i++) { int x; scanf("%d",&x); if(pos[x]&&ans>x) { ans=x; ansl=pos[x],ansr=i; } pos[x]=i; } for(int i=1; i<=maxm; i++) { ve.clear(); for(int j=i; j<=maxm; j+=i) { if(pos[j]) { ve.push_back(j); if(ve.size()==2)break; } } if(ve.size()==2) { if(ans>(ll)ve[0]*ve[1]/i) { ans=(ll)ve[0]*ve[1]/i; ansl=pos[ve[0]]; ansr=pos[ve[1]]; } } } if(ansl>ansr)swap(ansl,ansr); printf("%d %d\n",ansl,ansr); return 0; }