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,来判断方程是否有解。 ------------------------------------------------------------------------------------------求解 x,y: 我们可以通过求 a*x+b*y=gcd(a,b)的解,得出 a*x+b*y=m 的解。 1. 当 b==0的时候 gcd(a,b)=a。a*x+b*y=gcd(a,b)=a, 所以这个时候 x=1,y=0(其实这里 的 y 可以赋值为任意值) 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 求的 x1,y1。可以用欧几里德 递归的思想 ,递归下去, 直到 b=0,这时候 x=1,y=0。 这样在回溯的时候根据 不断修改 x,y。直到回溯结束,求的正确的解。 这个时候求得的只是 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), 这个是显然成立的。 可以通过 x 加减 b,y 减加 a, 来调节解的大小直到符合要求。 如果要求的解 x 是最小正整数的话,可以直接 x=(x%b+b)%b