zoukankan      html  css  js  c++  java
  • 算法15---数论5---最大公约数,最小公倍数

    算法16---数论5---最大公约数,最小公倍数

    有一个难点就是stein算法的证明;
     
     
     
    首先引进一个符号:g_c_d是greatest common divisor(最大公约数)的缩写,g_c_d( x,y ) 表示x和y的最大公约数。然后有一个事实需要了解:一个奇数的所有约数都是奇数。这个很容易,下面我们要用到。
      来研究一下最大公约数的性质,我们发现有 g_c_d( k*x,k*y ) = k*g_c_d( x,y ) 这么一个非常好的性质(证明我就省去了)。说他好是因为他非常符合我们化小的思想。我们试取 k=2 ,则有 g_c_d( 2x,2y ) = 2 * g_c_d( x,y )。这使我们很快联想到将两个偶数化小的方法。那么一奇一个偶以及两个奇数的情况我们如何化小呢?
     
      先来看看一奇一偶的情况: 设有2x和y两个数,其中y为奇数。因为y的所有约数都是奇数,所以 a = g_c_d( 2x,y ) 是奇数。根据2x是个偶数不难联想到,a应该是x的约数。我们来证明一下:(2x)%a=0,设2x=n*a,因为a是奇数,2x是偶数,则必有n是偶数。又因为 x=(n/2)*a,所以 x%a=0,即a是x的约数。因为a也是y的约数,所以a是x和y的公约数,有 g_c_d( 2x,y ) <= g_c_d( x,y )。因为g_c_d( x,y )明显是2x和y的公约数,又有g_c_d( x,y ) <= g_c_d( 2x,y ),所以 g_c_d( 2x,y ) = g_c_d( x,y )。至此,我们得出了一奇一偶时化小的方法。
     
     再来看看两个奇数的情况:设有两个奇数x和y,似乎x和y直接向小转化没有什么太好的办法,我们可以绕个道,把x和y向偶数靠拢去化小。不妨设x>y,我们注意到x+y和x-y是两个偶数,则有 g_c_d( x+y,x-y ) = 2 * g_c_d( (x+y)/2,(x-y)/2 ),那么 g_c_d( x,y ) 与 g_c_d( x+y,x-y ) 以及 g_c_d( (x+y)/2,(x-y)/2 ) 之间是不是有某种联系呢?为了方便我设 m=(x+y)/2 ,n=(x-y)/2 ,容易发现 m+n=x ,m-n=y 。设 a = g_c_d( m,n ),则 m%a=0,n%a=0 ,所以 (m+n)%a=0,(m-n)%a=0 ,即 x%a=0 ,y%a=0 ,所以a是x和y的公约数,有 g_c_d( m,n )<= g_c_d(x,y)。再设 b = g_c_d( x,y )肯定为奇数,则 x%b=0,y%b=0 ,所以 (x+y)%b=0 ,(x-y)%b=0 ,又因为x+y和x-y都是偶数,跟前面一奇一偶时证明a是x的约数的方法相同,有 ((x+y)/2)%b=0,((x-y)/2)%b=0 ,即 m%b=0 ,n%b=0 ,所以b是m和n的公约数,有 g_c_d( x,y ) <= g_c_d( m,n )。所以 g_c_d( x,y ) = g_c_d( m,n ) = g_c_d( (x+y)/2,(x-y)/2 )。
     
    我们来整理一下,对两个正整数 x>y :
    1.均为偶数 g_c_d( x,y ) =2g_c_d( x/2,y/2 );
    2.均为奇数 g_c_d( x,y ) = g_c_d( (x+y)/2,(x-y)/2 );
    2.x奇y偶 g_c_d( x,y ) = g_c_d( x,y/2 );
    3.x偶y奇 g_c_d( x,y ) = g_c_d( x/2,y ) 或 g_c_d( x,y )=g_c_d( y,x/2 );
     
    补充说明;
    最大公约数还有一种方法,就是用欧几里得算法求最大公约数;
    举例说明:
    求gcd(30,21)
    采用欧几里得算法:
    伪代码:
    euclid(a,b)
    if b==0
         return a;
    else return euclid(b,a mod b);
     
    example:
    euclid(30,21)=euclid(21,9)=euclid(9,3)=euclid(3,0)=3
     
     
      1 /*
      2     题目:最大公约数
      3     author taoliu——alex  2016.10   number4
      4 
      5     主要实现:
      6     求最大公约数
      7 
      8     我们主要采用两种方法来实现,一种是最常用的辗转相除法;
      9     另一种采用stein 算法
     10     第一种适合比较小的数字之间的计算;当时如果数据过大,就不适合了;
     11     stein算法就采用的是整数的以为和普通的加减方法实现的。
     12 
     13 
     14     再补充一种使用欧几里得算法求最大公约数的方法
     15 
     16 */
     17 
     18 
     19 
     20 
     21 
     22 #include <stdio.h>
     23 
     24 
     25 
     26 /*
     27 辗转相除法;
     28 */
     29 int gcd(int a,int b)
     30 {
     31     int m;
     32     int n;
     33     if (a>b)
     34     {
     35         m=a;
     36         n=b;
     37     }
     38     else
     39     {
     40         m=b;
     41         n=a;
     42     }
     43     int r=m%n;
     44     while(r!=0)
     45     {
     46         m=n;
     47         n=r;
     48         r=m%n;
     49     }
     50     return n;
     51 }
     52 
     53 
     54 /*
     55 方法2:stein算法;
     56 假设计算a和b两个数的最大公约数;
     57 (1)首先判断a或者b的值,如果a=0,b就是最大公约数,相反,a就是最大公约数;如果a和b都不为0;就执行下一步;
     58 (2)完成a1=a,b1=b,c1=1的赋值;
     59 (3)判断an,bn是否为偶数,若都为偶数,则使a(n+1)=an/2,b(n+1)=bn/2,c(n+1)=cn*2;如果判断an和bn中包含一个技术,则执行(4)(5)(6);
     60 (4)若an是偶数,bn是奇数,则完成a(n+1)=an/2,b(n+1)=bn,c(n+1)=cn的赋值;
     61 (5)若an是奇数,bn是偶数,则完成a(n+1)=an,b(n+1)=bn/2,c(n+1)=cn的赋值;
     62 (6)若an,bn是奇数,,则完成a(n+1)=|an-bn|,b(n+1)=min(an,bn),c(n+1)=cn的赋值;
     63 (7)n累加1,跳转到第(3)步进行下一轮运算。
     64 
     65 */
     66 
     67 int gcd2(int a,int b)
     68 {
     69     int m,n;
     70     if (a>b) //还是使用m保存较大的数;
     71     {
     72         m=a;
     73         n=b;
     74     }
     75     else
     76     {
     77         m=b;
     78         n=a;
     79     }
     80 
     81     if (n==0)
     82     {
     83         return m;
     84     }
     85     if (m%2==0&&n%2==0)
     86     {
     87         return gcd2(m/2,n/2);
     88     }
     89     if (m%2==0)
     90     {
     91         return gcd2(m/2,n);
     92     }
     93     if (n%2==0)
     94     {
     95         return gcd2(m,n/2);
     96     }
     97     return gcd((m+n)/2,(m-n)/2);
     98 }
     99 
    100 
    101 //欧几里得算法
    102 int euclid(int a,int b)
    103 {
    104     int m,n;
    105     if (a>b) //还是使用m保存较大的数;
    106     {
    107         m=a;
    108         n=b;
    109     }
    110     else
    111     {
    112         m=b;
    113         n=a;
    114     }
    115     if (n==0)
    116     {
    117         return m;
    118     }
    119     else
    120         return euclid(b,a%b);
    121 }
    122 
    123 
    124 int main()
    125 {
    126     int ans1=gcd(6,4);
    127     printf("%d
    ",ans1 );
    128     int ans2=gcd2(9,3);
    129     printf("%d
    ",ans2 );
    130     int ans3=gcd2(12,9);
    131     printf("%d
    ",ans3 );
    132     return 0;
    133 }
    最小公倍数源代码
     
     
     1 /*
     2     题目:最小公倍数
     3     author taoliu——alex  2016.10   number4
     4 
     5     主要实现:
     6     求最小公倍数
     7 
     8 
     9 */
    10 #include <stdio.h>
    11 
    12 
    13 
    14 int gcd(int a,int b)
    15 {
    16     int m;
    17     int n;
    18     if (a>b)
    19     {
    20         m=a;
    21         n=b;
    22     }
    23     else
    24     {
    25         m=b;
    26         n=a;
    27     }
    28     int r=m%n;
    29     while(r!=0)
    30     {
    31         m=n;
    32         n=r;
    33         r=m%n;
    34     }
    35     return n;
    36 }
    37 
    38 
    39 int lcm(int a,int b)
    40 {
    41     int c=gcd(a,b);
    42     int d=(a*b)/c;
    43     return d;
    44 
    45 }
    46 
    47 
    48 
    49 int main()
    50 {
    51     int ans=lcm(3,4);
    52     printf("%d
    ", ans);
    53     return 0;
    54 }
     
     
     
     
  • 相关阅读:
    【JVM】垃圾回收概述(十五)
    mysql命令查看某数据使用空间情况,索引,行数
    联合使用PrediXcan、MetaXcan基于GWAS结果预测靶基因及特异性组织的表达(又名全转录组分析Transcriptome-Wide AnalysisS)
    【Python基础编程009 ● Python入门 ● 输入 】
    【Python基础编程007 ● Python入门 ● 字符串的格式化操作符 】
    【Python基础编程006 ● Python入门 ● 输出的基本使用 】
    【Python基础编程005 ● Python入门 ● 标志符和关键字 】
    【Python基础编程004 ● Python入门 ● 变量的数据类型 】
    【Python基础编程003 ● Python入门 ● 变量的定义及其使用 】
    【Python基础编程002 ● Python入门 ● 注释 】
  • 原文地址:https://www.cnblogs.com/tao-alex/p/5941079.html
Copyright © 2011-2022 走看看