杭電ACM OJ 1019 Least Common Multiple 質因子最快速求最大公因數和最小公倍數
阿新 • • 發佈:2019-01-04
Least Common Multiple
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 56268 Accepted Submission(s): 21413
Problem Description The least common multiple (LCM) of a set of positive integers is the smallest positive integer which is divisible by all the numbers in the set. For example, the LCM of 5, 7 and 15 is 105.
Input Input will consist of multiple problem instances. The first line of the input will contain a single integer indicating the number of problem instances. Each instance will consist of a single line of the form m n1 n2 n3 ... nm where m is the number of integers in the set and n1 ... nm are the integers. All integers will be positive and lie within the range of a 32-bit integer.
Output For each problem instance, output a single line containing the corresponding LCM. All results will lie in the range of a 32-bit integer.
Sample Input 2 3 5 7 15 6 4 10296 936 1287 792 1
Sample Output 105
10296
翻譯:求多個數的最小公倍數
核心:明白求質因子的最快方法,可以參看我的部落格快速求質因子,這裡我也簡單講一下
雖然是java程式碼,但是和c c++也差不多
private static List<Integer> getPrimeFactor(int num) { List<Integer> primeFactorList = new ArrayList<>(); for (int i = 2; i * i < num; i++) { if (num % i == 0) { primeFactorList.add(i);while (num % i == 0) num = num / i; } } if (num > 1) primeFactorList.add(num); return primeFactorList; }
就是和正常求質因子不同的是,這裡添加了這樣一個操作
while (num % i == 0) num = num / i;這就是為了求出一個因子以後,這一類的因子以後都不用再考慮了,大大縮小了num的長度,增加了效率。
此外
if (num > 1) primeFactorList.add(num);由於num大大縮小,不會像原來一樣遍歷完全,所以可能會漏掉num本身。
所以問題就簡單了。
此外還需要考慮一個問題,兩個數之間的乘積 = 兩個數的最大公因數 * 兩個數的最小公倍數;
(原因:假設m = a*c,n = b *c(ab互質),那麼他們的公因數就是c,公倍數就是abc,乘積就是abcc,相等)
但是這個原理對多個數不適用,你們可以也一樣地推一下。
所以我們應該求出互不相同質因子的乘積,再去用乘積的2倍,3倍。。一直遍歷到可以把所有數的乘積整除,這樣就行了,非常簡單。
我把每個功能都分成了一個個小模組 十分的清晰
public class LeastCommonMultiple1019 { List<Integer> list = new ArrayList<>(); //初始化list LeastCommonMultiple1019(Integer...i) { Collections.addAll(list, i); } //把list裡的每個整數都求出質因子來,放入一個新集合,再把所有的集合放入一個新的乘方集合的集合, //相當於二維陣列 private List<List<Integer>> getPrimeFactor(List<Integer> list) { List<List<Integer>> allList = new ArrayList<>(); for (int i : list) { List<Integer> mList = new ArrayList<>(); int num = i; for (int j = 2; j * j < num; j ++) { if (num % j == 0) { mList.add(j); while (num % j == 0) num /= j;//一次性徹底消除一種因子 } } if (num > 1) mList.add(num); allList.add(mList); } return allList; } //根據這個“二維陣列”,找出每一列存放的質因子,留下互不相同的質因子 private List<Integer> getPrimeList(List<List<Integer>> list) { List<Integer> primeList = new ArrayList<>(); for (List<Integer> mList : list) { for (int i : mList) { if (!primeList.contains(i)) { primeList.add(i); } } } return primeList; } //把互不相同的質因子,進行處理,返回結果 private int getResult(List<Integer> list) { int product = 1; for (int i : list) { product *= i; } int max = -1; for (int i : this.list) { if (max < i) { max = i; } } int i = 2; while ((product * i) % max != 0) { i ++; } return product * i; } private int getAnswer() { List<List<Integer>> list = getPrimeFactor(this.list); List<Integer> primeList = getPrimeList(list); return getResult(primeList); } public static void main(String[] args) throws Exception { LeastCommonMultiple1019 leastCommonMultiple1019 = new LeastCommonMultiple1019(6,4,10296,936,1287,792,1); int answer = leastCommonMultiple1019.getAnswer(); System.out.println(answer + ""); } }