zoukankan      html  css  js  c++  java
  • 如何思索算法(一)

    如何思索算法(一)
    今天在刷网页的时候发现一个求最小公倍数的问题,感觉颇有意思就拿来看,有意思的不是题目而是我在解决该问题时所做的探索。
    题目:求能被1~n所有数整除的最小正数(最小公倍数)。
      一眼瞅去一点思路都没有,只想从1*2*3*4*.....*n的结果就一定能够除所有1到n。但是这个数不是最小的,因为存在因子冗余。比如说:能够被8整除的数一定可以被2整除,被9整除的数一定可以被3整除。下面来一步一步的思考如何解决该问题:
      考虑1~10的情况:1、2、3、4、5、6、7、8、9、10。设置一个因子数组factor(10)。
      首先,去除1,这一点毫无疑问,不解释。
      其次,选出素数2、3、5、7放入factor中。这些数一定是所求最小整数的因子,因为它们只能被1和自身整除。此时,factor[(10)={2、3、5、7}
      然后,剩下的数有4、6、8、9、10。分解因子:
      4=2*2;
      6=2*3;
      8=2*4;
      9=3*3;
      10=2*5;
      分析,去掉6和10,因为2*3=6,2*5=10,因为在我们的素数中存在2、3、5。如果要能被9整除则必须包含两个3,向factor中添加一个3。最后考虑4和8,如果要能被8整除则必须有2*4,因为求最小的整数,所以因子小的保留。到此,factor(10)={2、3、5、7、4、3}问题得到解决该最小整数是2*3*4*5*7*3=2520。
      考虑1~20的情况:1、2、3、4、5、6、7、8、9、10、11、12、13、14、15、16、17、18、19、20。设置一个因子数组factor。
      首先,从大到小缩减范围。能够被11、12、13、14、15、16、17、18、19、20整除的数一定可以整除11、12、13、14、15、16、17、18、19、20。
      其次,选出11~20中的素数加入factor中。此时factor(20)={11、13、17、19}。
      然后,剩下的数有12、14、15、16、18、20。分解因子:
      12=2*6---->2*2*3
      14=2*7
      15=3*5
      16=2*8----->2*2*4------->2*2*2*2
      20=2*10---->2*2*5
      对因子进行删重去除冗余,剩余2、2、5、7、4、3、3加入数组factor,此时factor(20)={2、2、5、7、4、3、3、11、13、17、19}
      结果为2*5*7*4*3*3*11*13*17*19=232792560。
      Factor(10)={2、3、5、7、4、3}
      factor(20)={2、5、7、4、3、3、11、13、17、19、2}
      发现规律了吗?
      现在我可以立即写出1~30的最小公倍数的因子
      Factor(30)={2,3,5,7,11,13,17,19,23,29,2,2,2,3,3,5}。
      红色的是1~30的所有素数。为什么在后边添加了2,2,2,3,3,5呢?因为在1~30中包含了16,25,27这三个特别数字,为什么特别,因为它们需要2的4次方,5的2次方和3的3次方得到。也就意味着在factor中必须出现4次,2次和3次。
      因此很容易得到该问题的算法实现了:
      1、计算1~n的所有素数{a1,a2,a3........an}
      2、依次从小到大检查素数的幂次方,记录下不大于n的幂次m。
      3、将该素数的m次方与其他素数累乘。
          4、重复2、3,直到所有素数都被检查完。

    下面给出该问题的java实现

    public static long 最小公倍数(int n){
            long result = 1;
            int primes[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
            List list = new ArrayList();
            List exlist = new ArrayList();
            for(int i=0;i<primes.length;i++){
                if(primes[i]<n){
                    list.add(primes[i]);
                }
            }
            for(int i=0;i<list.size();i++){
                int t =(Integer) list.get(i);
                int q = 0;
                int multis=t;
                for(;;q++){
                    multis*=t;
                    if(multis>n){
                        for(int j=0;j<q;j++){
                            exlist.add(t);
                        }
                        break;
                    }
                }
            }
            
            for(int i=0;i<list.size();i++){
                int t =(Integer) list.get(i);
                result*=t;
            }
            for(int i=0;i<exlist.size();i++){
                int t =(Integer) exlist.get(i);
                result*=t;
            }
            System.out.println(list.toString());
            System.out.println(exlist.toString());
            return result;
        }

    其实,任何自然数都可以通过素数的n次幂的乘积表示,即

    N=(2^n)*(3^n)*(5^n)*(7^n)*(11^n)*(13^n)*(17^n)*............

    这也正是程序实现的数学支持。如果知道该公式,我们就可以省却很多功夫,不用一点一点自己去总结发现规律,一下就能知道如何解决,但是思维的延伸却不能这样懒省事,要积极的去进行探索才能迸出创造的火花。

  • 相关阅读:
    Solution: Win 10 和 Ubuntu 16.04 LTS双系统, Win 10 不能从grub启动
    在Ubuntu上如何往fcitx里添加输入法
    LaTeX 笔记---Q&A
    Hong Kong Regional Online Preliminary 2016 C. Classrooms
    Codeforces 711E ZS and The Birthday Paradox
    poj 2342 anniversary party
    poj 1088 滑雪
    poj 2479 maximum sum
    poj 2481 cows
    poj 2352 stars
  • 原文地址:https://www.cnblogs.com/danger/p/2939392.html
Copyright © 2011-2022 走看看