codeforces#1154G. Minimum Possible LCM(最小公倍數)
阿新 • • 發佈:2019-04-25
long long names main swap can $1 space force class
題目鏈接:
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; }
codeforces#1154G. Minimum Possible LCM(最小公倍數)