1 欧几里得算法标准代码
这个代码算的是符合a * x + b * y = gcd(a, b)的一组x, y, 同时返回了gcd(a, b)
因为a * x1 + b * y1 = gcd(a, b)
gcd(a, b) = gcd(b, a % b)
那么a * x1 + b * y1 = gcd(b, a % b) = b * x2 + (a - a/b*b) * y2; // a % b = a - a/b*b;而且x2, y2是更内层的
把上面得到的式子变形得 a * x1 + b * y1 = a * y2 + b * (x2 - a / b * y2);
对应x1 = y2, y1 = x2 - a / b * y2;
里面一层有返回值的时候想着返回上一层就好理解了,比如对应x1 = y2, y1 = x2 - a / b * y2;可以理解为上一层的y2赋给这一层的x1,上一层的 x2 - a / b * y2赋给y1
__int64 exGcd(__int64 a,__int64 b,__int64 &x,__int64 &y) { if(b==0){ x=1; y=0; return a; } __int64 g=exGcd(b,a%b,x,y); __int64 temp=x; x=y; y=temp-(a/b)*y; return g; }
2求 a * x + b * y = c的解
就是根据上面模板算出gcd(a, b)的同时算出a * x + b * y = gcd(a, b)的解,
然后x = x * c / gcd(a, b); y = y * c / gcd(a, b);
其中,a*x+b*y = c有整数解的充要条件是gcd(a, b)|c;
#include <cstdio> __int64 exGcd(__int64 a,__int64 b,__int64 &x,__int64 &y) { if(b==0){ x=1; y=0; return a; } __int64 g=exGcd(b,a%b,x,y); __int64 temp=x; x=y; y=temp-(a/b)*y; return g; } int main() { __int64 a, b, c, x, y, gc; while(scanf("%I64d%I64d%I64d", &a, &b, &c) == 3) { gc = exGcd(a, b, x, y); if(c % gc) { printf("无解 "); continue; } else printf("%I64d %I64d ", x*c/gc, y*c/gc); } }
3 求逆元
这个算法好久之前就想搞定,今天终于搞定了,好开心啊
求a在mol b下的逆元, 即求满足a * x ≡ 1 (mod b)的x //要求a和b互质
套用扩展欧几里得模板,则苛求出来 满足 a * x + b * y = gcd(a, b)的x, 因为a,b互质,故gcd(a, b) = 1所求x即a在mod b情况下的逆元,
输出大于0且最小的答案,所以 x = (x % b + b) % b;
#include <iostream> using namespace std; void exgcd(int a, int b, int &x, int &y) { if(b==0) { x = 1; y = 0; return; } exgcd(b, a%b, x, y); int t = x; x = y; y = t - a/b*y; } int main() { int b,mod, x, y; while(cin>>b>>mod) { exgcd(b,mod, x, y); cout<<(x%mod+mod)%mod<<endl; } return 0; }