您的位置:首页 > 其它

欧几里得与扩展

2018-06-17 08:36 183 查看
欧几里得:

gcd递归定义:对于任意正整数b,gcd(a,b)= gcd(b,a mod b)。

证明:

  

  只需要证明上面两者能相互整除。

  设gcd(a,b)= d,所以d | a 且 d | b。由带余除法可以得出:

  a mod b = a - qb。其中 q = └a / b┘.所以 a mod b 是a 和 b的一个线性方程组合,
  
  所以d |a mod b。又因为 d | b,所以 d | gcd(b,a mod b),即gcd(a,b)|gcd(b,a mod b)。
  
  证明gcd(b,a mod b)|gcd(a,b)和上述过程几乎一样。


  

代码实现:

  

#include <iostream>
#include <cstdio>
using namespace std;
int a,b;
int gcd(int a,int b)
{
if(a<b)swap(a,b);        //此处注意,why?仔细想想。
return a%b==0?b:gcd(b,a%b);
}
int main()
{
scanf("%d%d",&a,&b);
printf("%d",gcd(a,b));
}


gcd 比较简单,接下来才是重头戏 --- 扩展。

扩展欧几里得:

  这东西看似没啥用,实际其应用范围很广(逆元,不定方程...)。

  现在我们有这样一个问题:

    求解不定方程 ax + by = gcd(a,b).(假设 a >= b ).

 

当 b=0 时有 gcd(a,b)=a,此时 x=1,y=0

当 b 不为 0 时,根据 GCD 递归定理 gcd(a,b)=gcd(b, a mod b)

可得 ax+ by=gcd(a, b)=gcd(b, a mod b)=bx′ +(a mod b)y′

即 ax+by=bx′+(a mod b)y′ = bx′+(a−b)×⌊a/b⌋y′

移项得 ax+by=bx′+(a mod b)y=ay'+b(x-⌊a/b⌋y)

所以x=y',y=x'-⌊ a/b ⌋y'.


  设(xo,yo)是不定方程 ax+by=m 的一组解,(a,b)=g,那么全部解为

    (xo+(b/g)t , yo - (a/g)t),其中 t 为所有整数.

  

模板代码:

#include <cstdio>
int exgcd(int a, int b, int &x, int &y)        //非递归版
{
int d;
if (!b) x = 1, y = 0, d = a;
else
{
d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
}
return d;
}
int exgcd(int a, int b, int &x, int &y)        //递归版
{
int d;
return !b ? (x = 1, y = 0, a) : (d = exgcd(b, a % b, y, x), y -= (a / b) * x, d);
}
int main()
{
int a, b, x, y;
scanf ("%d%d", &a, &b);
printf("%d\n", exgcd(a, b, x, y));
printf("%d %d\n", x, y);
}


习题练习:

  NOIP 2012 同余方程

  求关于 x 的同余方程ax ≡ 1(mod b) 即求解 ax + by = 1 中的 x 值,注意题目要求 正整数。

  不是模板,胜似模板。

  代码:

#include <cstdio>
int exgcd(int a, int b, int &x, int &y) {
int d;
return !b ? (x = 1, y = 0, a) : (d = exgcd(b, a % b, y, x), y -= (a / b) * x, d);
}
int main()
{
int a, b, x, y;
scanf ("%d%d", &a, &b);
exgcd(a, b, x, y);
int k=(0-x) /b;
x=x+k*b;
while(x<0){ x+=b; }     //处理负数
printf("%d", x);
}


作者:RMY

出处:https://www.cnblogs.com/rmy020718/p/9192002.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: