欧几里德和扩展欧几里得

1.欧几里德(辗转相除法)
用处:求a,b 两个数最大的公约数
利用递归来实现,或者在主函数中用循环实现
代码

#include<stdio.h>
int gcd(int a,int b)
{
if(a%b==0)
    return b;
else 
    return gcd(b,a%b);
}
int main()
{
    int a,b;
    scanf("%d%d",&a,&b);
    printf("max:\n");
    printf("%d\n",gcd(a,b));
    return 0;
}

2.扩展欧几里德 (注:x(n)n代表下表,下面都是如此)
方程式ax+by=c,已知a,b,c,求x,y?
扩展欧几里德中c要是gcd(a,b)的倍数,才会有整数解
为什么一定要等于最大公约数呢?
//本质a 和b是互质的(互质:代表两个数最大公约数为1) 并且最大公约数为1;
//例如  2x+4y=1;是求不出来的;如果2x+4y=2 就是成立的  因为2(x+2y)=2 --x+2y=1 是可以转变的
//ax+by=d;
//a=m*d;b=n*d;
//m*d*x+n*y*d=d;
//mx+ny=1;
//所以互质情况下d就为1,他们可以同时扩大倍数,就像刚刚上面举的2x+4y=2这个例子;
c如果不是d的倍数就没有整数解,但是可以有小数解;
因为ax+by=gcd(a,b),所以设他们的最大公约数为d
所以ax+by=d
根据欧几里德得知:gcd(a,b)=gcd(b,a%b)
                 gcd(a,b)=gcd(b,a)
b*x1+a%b*y1=d;
所以b*x1+a-[a/b]/b*y1=d
所以x=y1;y=x1-a/b*y1;
递归下去直至b=0,a就是最大公约数;
所以 d*x(n)+0*y(n)=d;
所以x(n)=1,y(n)任意 推出他之前的x(n-1)和y(n-1);
直至推出x和y;
代码:例如青蛙约会的题POJ 1061

<p>#include<stdio.h>
 long long  m,n,l,y,x,k;
 long long  X,Y,a,b,c,t,d;</p><p>int extend_gcd(int a,int b)
{
  if(b==0)
  {
  X=1;
  Y=0;
  return a ;
  }
  d=extend_gcd(b,a%b);
  t=X;                   //用t来保存本次的x,因为下面的会变
  X=Y;
  Y=t-(a/b)*Y;
  return d;
}
int main()
{
    scanf("%d%d%d%d%d",&x,&y,&m,&n,&l);
    a=m-n;
    b=-l;
    c=y-x;
    d=extend_gcd(a,b);
    if(c%d!=0)
    {
    printf("Impossible\n");
    return 0;
    }
    X=X*(c/d);
    Y=Y*(c/d);
    //X=X+k(b/d);        //使通解最小  通解见下面解释
    k=X/(b/d);          // k应与x符号相反
    X=X-k*b/d;
    if(X<=0)            X+=b/d;
    printf("%lld",X);</p><p>
return 0;
}
</p>

因为把c变成了d,所以c=d*(c/d);
x 和 y 都* c/d;
求出一组x和y就能求出他的通解
ax+m+by-m=c;
m是ab的最小公倍数,m=a*b/d; //最小公倍数是两个数相乘除以最大公约数
为什么是最小公倍数,因为要使m/a是整数并且最小;
使x的跨步小;
a*(x+m/a)+b(y-m/b)=c;
所以
a(x+b/d)+b(y-a/d)=c
通解就为
x0=x0+k*b/d;
y=y0-k*a/d;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值