zoukankan      html  css  js  c++  java
  • 1~N的最小公倍数

    题目

    输入整数N,计算1~N这N个数的最小公倍数,N<100

    思路

    思路其实很清晰,只要求得了前N-1个数的最小公倍数a,那么N个数的最小公倍数就是a和N的最小公倍数。求两个整数(a,b) 的最小公倍数就是 (frac{a imes 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

  • 相关阅读:
    xuexi
    太厉害了!腾讯T4大牛把《数据结构与算法》讲透了,带源码笔记
    python 死循环
    redis 锁
    Opencv4.1.0交叉编译----终端摄像头内算法嵌入,海思HISI、雄迈ARM编译链使用经验
    SpringCloud之FeignClient调用跨微服接口
    Elasticsearch父子级查询及祖孙辈parent/child关联查询
    服务器ip地址与域名解析及http转https
    RestTemplate请求第三方接口添加Headers token及设置请求体
    kanzi 一些基础参数变量
  • 原文地址:https://www.cnblogs.com/rezero/p/13179237.html
Copyright © 2011-2022 走看看