1. 程式人生 > >杭電ACM OJ 1019 Least Common Multiple 質因子最快速求最大公因數和最小公倍數

杭電ACM OJ 1019 Least Common Multiple 質因子最快速求最大公因數和最小公倍數

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 + "");
}
}