1~N的最小公倍數


題目

輸入整數N,計算1~N這N個數的最小公倍數,N<100

思路

思路其實很清晰,只要求得了前N-1個數的最小公倍數a,那么N個數的最小公倍數就是a和N的最小公倍數。求兩個整數\(a,b\) 的最小公倍數就是 \(\frac{a\times b}{gcd(a,b)}\)\(gcd(a,b)\)為a和b的最大公約數。看起來似乎很簡單,但是這里有個大坑:值越界。
題目中限制了N<100,但是當 N=23 的時候,計算得到的最小公倍數為5354228880已經遠遠超過了int型的表示范圍。

方法一

通過質因數求解。例如對於4和10,4的質因數為(2,2),10的質因數為(2,5)。由於他們有一個公共質因數2,所以最小公倍數為2*2*5=20。
所以第一步先求所有N個數的質因數,重復的質因數只能算一次,接下來將所有質因數相乘就可以得到最小公倍數。但其實這里還是有大數的問題,所以需要通過大數相乘的方法計算,也就是通過數組保存大數。代碼如下:

import java.util.Scanner;
public class Main{
    
    public static void main(String[] arg){
        
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        
        int[] a = new int[105];      // a[1]~a[N]存儲   1~N 的N個數的所有質因數
        int[] nums = new int[100];  // 將結果從低位到高位存在一個數組里
        for(int i = 1; i <= 101; i++){
            a[i] = i;
        }
        
        // 計算質因數存到a中
        // 此時實質上a[1]*a[2]*...*a[N]就是1~N的最小公倍數
        // 但直接相乘會數值溢出,因此用數組來進行大數相乘
        for(int i = 2; i <= 101; i++){
            for(int j = i + 1; j <= 101; j++){   
                if(a[j] % a[i] == 0){
                    a[j] /= a[i];
                }
            }
        }
        
        nums[0] = 1;
        // tag存放進位,count存放有效數組長度
        int tag = 0, count = 0;
        for(int i = 2; i <= n; i++){
            if(a[i] > 1){  // 減少不必要的計算
                for(int j = 0; j <= count || tag > 0; j++){
                    int tmp = nums[j] * a[i] + tag;
                    nums[j] = tmp % 10;
                    tag = tmp / 10;
                    if(j > count){  // 更新有效長度
                        count = j;
                    }
                }
            }
        }
        
        while(count >= 0){   // 最后將nums中的有效數字從高位到低位輸出
            System.out.print(nums[count]);
            count--;
        }
        System.out.println();
    }
}

方法二

java.math包中提供了BigInteger類用來處理大整數的問題。這里用另一種思路:小於N的質數最大冪乘積的方式。
例如N=10,小於10的質數有:2,3,5,7
對應的最大冪分別為:3,2,1,1(即質數的最大冪次方小於N)
因此前1~10的最小公倍數為2^3 * 3^2 * 5 * 7 = 2520
代碼如下:

import java.math.BigInteger;
import java.util.Scanner;
public class Main{
    
    public static void main(String[] arg){
        
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        
        BigInteger ans = BigInteger.ONE;
        for(int i = 2; i <= n; i++){
            int tmp = 1;
            if(isPrime(i)){
                while(tmp * i <= n){
                    tmp *= i;
                }
            }
            ans = ans.multiply(BigInteger.valueOf(tmp));
        }
        System.out.println(ans);
    }
    
    private static boolean isPrime(int a){
        for(int i = 2; i <= Math.sqrt(a); i++){
            if(a % i == 0){
                return false;
            }
        }
        return true;
    }
}

參考來源

https://blog.csdn.net/sharing_li/article/details/8737855?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-1
https://www.xuebuyuan.com/2857576.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM