B. Minimum Possible LCMios
time limit per test算法
4 secondsthis
memory limit per testspa
1024 megabytes.net
inputcode
standard inputblog
outputip
standard outputci
You are given an array aconsisting of integers a1,a2,…,*a**n*element
Your problem is to find such pair of indices i,j that lcm(\(a_i\),\(a_j\))is minimum possible.
lcm(x,y) is the least common multiple of and x and y(minimum positive number such that both x and y are divisors of this number).
Input
The first line of the input contains one integer n — the number of elements in a
The second line of the input contains n integers a1,a2,…,an (1≤ai≤107), where ai is the i-th element of a.is the i.
Output
Print two integers i and (1≤i<j≤n is minimum among all valid pairs i,j
題目是要求一組數中兩個數的最小公倍數的最小值。剛開始一個直白的想法就是枚舉,把每兩個數的gcd求出來,根據gcd求每兩個數的lcm。這種作法的時間複雜度爲O(\(n^2\log_2 n\)),在看看題目的數據範圍,顯然不太科學,限時4秒,\(10^{12}log_210^{6}\),會遠遠超時。怎麼辦?
咱們來想想,通常lcm問題與gcd問題是掛鉤的。怎麼樣來求,因爲數據的範圍給定了,考慮枚舉數的因子,從1開始到\(10^7\),在數列中找到一因子爲最大公約數的兩個最小數,就是答案。爲何?
假設如今枚舉到了公因子d,數列中是d的倍數的有\(x_1\)<\(x_2\)<\(x_3\)<...<\(x_n\),若是d是\(x_1\),\(x_2\)的gcd,那麼也就知足條件,x1,x2的最小公倍數確定最小(在d爲因子時)。若是d不是x1,x2的gcd,那也不是後面數的gcd,那麼最大公倍數就不會最小。
因爲d是從小到大枚舉的,若是在d時知足條件,確定爲局部最優解。若是都不知足d爲gcd,d++,繼續枚舉直到知足。因爲算法必定會終止,算法的正確性就有了保障。算法複雜度是O(\(n\log_2 n\))
須要注意的是當元素有重複的狀況,那麼這種元素的最小公倍數就是自己,並且只多是最小重複元素的時候,由於若是比它大的重複元素的lcm必定大於它,不會是全局最小lcm,單獨在輸入的時候不斷覆蓋,留下最小的一種便可。
注意LLONG_MAX和LONG_MAX是不同的,我一開始錯了,原來由於是數不夠大。
#include <iostream> #include <climits> #define INF LLONG_MAX #define max_n 10000007 using namespace std; long long a[max_n]; int n; int pos[max_n]; long long ans = 0; long long minm = INF; int x = 0; int y = 0; long long gcd(long long a,long long b) { return (b==0)?a:gcd(b,a%b); } int main() { cin >> n; for(int i = 1;i<=n;i++) { int v; cin >> v; a[v]++; if(a[v]>1&&v<minm) { minm = v; x = pos[v]; y = i; } pos[v] = i; } for(int i = 1;i<max_n;i++) { long long v = 0; for(int j = i;j<max_n;j+=i) { if(a[j]==0) { continue; } if(v==0) { v = j; } else { long long g = gcd(v/i,j/i); if(g==1) { ans = (long long)j/i*v; if(ans<minm) { //cout << "v " << v << " j " << j << endl; minm = ans; x = pos[v]; y = pos[j]; } } break; } } } if(x>y) swap(x,y); cout << x << " " << y << endl; return 0; }
KobeDuu,Minimum Possible LCM【枚舉】,https://blog.csdn.net/qq_41157137/article/details/89353527