exp_euler两种形式int,void(扩展欧几里得算法)可求最大公约数,二元一次方程的解

int x,y,d;
void exp_gcd(int a,int b)
{
 int temp;
 if(b==0)
 {
  x=1;
  y=0;
  d=a;//最大公约数为d
 
 }
 else//必须有
 {
     exp_gcd(b,a%b);
     temp=x;
     x=y;
     y=temp-(a/b)*y;
 }
}

  int x,y;
int exp_gcd(int a,int b)//返回值为最大公约数
{
 int temp,p;
 if(b==0)
 {
  x=1;
  y=0;
  return a;
 }
 else//这里的else可以不要,因为return了就不会做下面。
 {
     p=exp_gcd(b,a%b);
     temp=x;
     x=y;
     y=temp-(a/b)*y;
  return p;
 }
}

//摘抄的解释

a*x+b*y=m。显然存在 gcd(a,b)|a*x , gcd(a,b)|b*x,如果方程有解的话,那么一定存在 gcd(a,b)|m 。 所有可以通过判断 m%gcd(a,b) 是否为0,来判断方程是否有解。 ------------------------------------------------------------------------------------------求解 xy: 我们可以通过求 a*x+b*y=gcd(a,b)的解,得出 a*x+b*y=m 的解。 1. 当 b==0的时候 gcd(a,b)=aa*x+b*y=gcd(a,b)=a, 所以这个时候 x=1y=0(其实这里 的 可以赋值为任意值) 2. a*x1+b*y1=gcd(a,b)--------------------------------------------------------------① b*x2+(a%b)*y2=gcd(b,a%b) 化啊化 b*x2+(a-(a/b)*b)*y2=gcd(b,a%b)-------② 根据欧几里德原理有 gcd(a,b)=gcd(b,a%b), 在根据① ② 得 a*x1+b*y1=b*x2+(a-(a/b)*b)*y2------------------------------------------③ ③式化啊化,得 a*x1+b*y1=a*y2 + b*( x2 –(a/b)*y2)------------------------④ ③④对应系数相等:x1=y2, y1= x2 –(a/b)*y2 ------------------------------------------------------------------------------------------这样可以基于 x2,y2 求的 x1y1。可以用欧几里德 递归的思想 ,递归下去, 直到 b=0,这时候 x=1y=0。 这样在回溯的时候根据 不断修改 xy。直到回溯结束,求的正确的解。 这个时候求得的只是 a*x+b*y=gcd(a,b)的解。 只要把 x*m/gcd(a,b), 就是 a*x+b*y=m 的解了。 。 这样看代码就很好理解了: #define LL __int64 LL exp_gcd(LL a,LL b,LL&x,LL&y) { LL temp,p; if(b==0) { x=1; y=0; return a; } p=exp_gcd(b,a%b,x,y); temp=x; x=y; y=temp-(a/b)*y; return p; } x1=y2, y1= x2 –(a/b)*y2 有些题目需要我们求得的解为 最小正整数,这就需要我们对求的解做一些处理。 a*(x+b*n) + b*(y-a*n)=gcd(a,b), 这个是显然成立的。 可以通过 加减 b减加 a 来调节解的大小直到符合要求。 如果要求的解 是最小正整数的话,可以直接 x=(x%b+b)%b 

原文地址:https://www.cnblogs.com/heqinghui/p/2606145.html