最大公约数求法

(PS:如果发现哪里错误,欢迎指出,万分感谢!!!)

定义:

      公约数:设 a1,a2,.....,an(n>=2)个整数。若整数d是它们中每一个数的因数,则 d 就叫做a1,a2,……,an的一个公因数。

      最大公因数:如果整数a1,a2,.......,an不全为0,那么整数a1,a2,.......,an的所有公因数中最大的一个公因数就叫做最大公因数,记作(a1,a2,.......,an)。

某些简单性质:

     1. 设b是任一整数,则(0,b)= b;

     2.同上,(1,b) = 1;

     3.设a,b是任一整数,则(a,b) =  (a,b);

     4.设a,b是任意两个不全为0的整数,

          (1.)若m是任一整数,则(m×a,m×b) = m×(a,b);

      方法:

              广义欧几里德除法(辗转相除法):

                      定理:   设a,b,c是三个不全为零的整数。如果

                                               a = q × b + c  ;

                      其中 q 是整数,则(a,b) = (b,c).

               基于以上定理,求a,b的最大公因数,只需要判断  c = a % b 是否等于0即可,如果c不等于0,就往下除,将a换成b,b换成c   即判断 b % c 是否等于0。只要c = 0,则a,b的最大公因数一定是 b;

               例:求(1859,1573):

                           1859 = 1 ×1573 + 286;      /// 286 = 1859 % 1573

                           1573 = 5 × 286 + 143;       /// 143 = 1573 % 286

                           286 = 2 × 143 + 0;              /// 0 = 286 % 143

                所以 (1859,1573) = 143; 

以下为代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;

int gcd_2(int a,int b){           /// 求两个数的最大公约数
    if(!a) return b;              ///性质1
    if(!b) return a;              
    if(a == 1 || b == 1) return 1;    ///性质2
    int c = a % b;
    return c == 0 ? b : gcd_2(b,c);
}
int gcd_3(int a,int b,int c){     /// 求三个数的最大公约数
    return gcd_2( gcd_2(a,b), gcd_2(a,c) );
}
int main()
{
    int x,y,z;
    while(~scanf("%d%d%d",&x,&y,&z)){
        printf("%d %d ",gcd_2(x,y),gcd_2(x,z));
        printf("%d\n",gcd_3(x,y,z));
    }
    return 0;
}

最大公因数的进一步性质:
                 设a,b,c 是三个整数,且b  != 0 ,  c != 0.如果(a,c) = 1,  则   (ab , c)  = ( b , c)。
  多个整数的最大公因数的计算:
              设a1 , a2 , ……,an是n 个整数,且a1 != 0 。令
                       (a1,a2)= d2,(d2,a3)= d3,……,(dn-1,an)= dn
             则(a1,a2,a3,……,an)= dn;


 
#include <iostream>
using namespace std;


int a[100000];
int gcd_2(int a,int b){      //求2个数的最大公因数   
    if(!a) return b;           
    if(!b) return a;              
    if(a == 1 || b == 1) return 1;   
    int c = a % b;
    return c == 0 ? b : gcd_2(b,c);
}
int gcd_n(int a[],int n){    //求多个数的最大公因数 
	int d = gcd_2(a[1],a[2]);
	for(int i = 2; i <= n; ++i)
		d = gcd_2(d,a[i]);
	return d;
}
int main(int argc, char *argv[]) {
	int n;
	cin>>n;
	for(int i = 1; i <= n; ++i) cin>>a[i];
	cout<<gcd_n(a,n)<<endl;
	return 0;
}


对于2^a  - 1 的整数的最大公因数
            设a,b是2个整数,则2^a - 1 和 2^b - 1 的最大公因数是 2^(a , b) - 1

         



对于最大公约数求s,t。

即  a,b的最大公约数,一定存在2个正数满足 s×a + t × b = (a,b)。求s,t 的方法:(自己花了一下午总结出来的做法,其实还有更简单的方法,大家可以百度)

          此公式基于欧几里德辗转相除法

           满足公式:   a0  =  (1)

                                  a1  =  (2)*a0  + 1

                                  a2  =  (3)*a1  +  a0;

                                  a3  =  (4)*a2  +  a1;

                                  .......

                                  a(n-1) = (n)*a(n-2) + a(n-3);

           (n) 代表了   辗转相除的每一步的除数,即 (n)= a / b   (a , b 参见上面gcd_2(a,b) 函数里的每一步的a,b)

        求得  s = a(n-2)  ;   t  =  a(n-1);     如果n是奇数,则s是正的,t是负的;反之,s是负的,t是正的  

        举个栗子:

               求(44350,20785)的  s,t  :

           辗转相除法的步骤是:

                   44350 = 2×20785 + 2780                          (5)= 2         a4  =  (5) * a3  +  a2  =  2 * 800 + 107  = 1707

                   20785 = 7×2780   + 1325                          (4) = 7         a3 =  (4)* a2  +  a1  =  7 * 107 + 51  = 800

                   2780   = 2×1325    + 130                            (3) = 2        a2  =  (3) * a1  +  a0  =  2 * 51 + 5  = 107

                   1325  =  10×130 + 25                                 (2)= 10       a1   =  (2)*a0  + 1  =  10 * 5 + 1 = 51

                   130  = 5*25  +   5                                         (1)= 5          a0  =  (1) = 5

                   25   =  5*5  +  0

               所以(44350,20785)  =  5; s = a3 = 800 ; t = a4 = -1707 ( n = 5是奇数)

              所以  (44350,20785)  =  5  =  44350×800 - 1707 × 20785   

                    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值