返回gcd(a,b)gcd(a,b),并计算方程:ax+by=gcd(a,b)ax+by=gcd(a,b)的一个解
#include<stdlib.h>
#include<stdio.h>
int e_gcd(int a, int b, int * x, int *y) {
if (b == 0) {
*x = 1;
*y = 0;
return a;
}
int ans = e_gcd(b, a%b, x, y);
int temp = *x;
*x = *y;
*y = temp - a / b*(*y);
return ans;
}
int main() {
int a = 8, b = 3;
int x, y;
int result = e_gcd(a, b, &x,&y);
printf("gcd(%d,%d)=%d,%d*a+%d*b=%d", a, b, result, x, y, result);
return 0;
}
intint a,b,m>0a,b,m>0,求使a+kbm是整数的最小的k:a+kbm是整数的最小的k:
想法:比如 8+4k6=t<=>6t−4k=8(∗)8+4k6=t<=>6t−4k=8(∗)
先求解6x−4y=gcd(6,4)=2的一组解(x0,y0),这是扩展欧几里得算法先求解6x−4y=gcd(6,4)=2的一组解(x0,y0),这是扩展欧几里得算法
两边乘以某个数,使得8出现在右边,这里乘以agcd(m,k)=82,两边乘以某个数,使得8出现在右边,这里乘以agcd(m,k)=82,
等式变为6(4x0)−4(4y0)=8,我们这样主要为了得到(∗)的一组解(4x0,4y0)而已等式变为6(4x0)−4(4y0)=8,我们这样主要为了得到(∗)的一组解(4x0,4y0)而已
然后就可以的到所有解:
设有两组解:6x1−4y1=86x1−4y1=8,6x2−4y2=86x2−4y2=8,相减:
6(x1−x2)=4(y1−y2)6(x1−x2)=4(y1−y2)
,发现了所有解的规律,x=x0+mgcd(m,b)tx=x0+mgcd(m,b)t
y=y0+bgcd(m,b)ty=y0+bgcd(m,b)t
,注意这里的y前面是负号,扩展欧几里得的负号是正的,选出需要的那个最小的y就不说了。
#include<stdlib.h>
#include<stdio.h>
int e_gcd(int a, int b, int * x, int *y) {
if (b == 0) {
*x = 1;
*y = 0;
return a;
}
int ans = e_gcd(b, a%b, x, y);
int temp = *x;
*x = *y;
*y = temp - a / b*(*y);
return ans;
}
int min_k(int a, int b, int m) {//求(a+kb)/m是整数中最小的k
int x = 0, y = 0;
int k1 = e_gcd(m, b, &x, &y);
if (a%k1 != 0) printf("无解\n"); exit(0);
y *= a / k1;//这是一个特解
y = -(((y%(m/k1))-(m/k1))%(m/k1));
return y;
}
int main() {
int ress=min_k(6, 4, 5);
printf("%d\n", ress);
}