您的位置:首页 > 其它

最大公约数求法

2016-03-07 17:44 211 查看
(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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: