扩展欧几里得
2017-08-23 17:22
155 查看
扩展欧几里得算法试求gcd(a,b)的一个非常高效的算法,具体内容是gcd(a,b)=gcd(b,a%b)。它可以再log时间内求出结果。
什么是扩展欧几里得?
考虑一个问题,如果我们知道a和b的最大公约数c,现在需要求出a*x+b*y=c的通解。这该怎么办?
不难看出通解形式一定是
x=x0+(b/c)*t,y=y0-(a/c)*t。那么该如何求出x0和y0?
首先不难看出x=1,y=0这一特解,我们要考虑的是能否通过这一特解推出结果。
根据欧几里得算法,再求gcd(a,b)时已经的出gcd(b,a%b),那么一定有b*x1+(a%b)*y1=c。
对与这一等式可以转化为:b*x1+(a-a/b*b)*y1=c ==> a*y1+b(x1-a/b*y1)=c。很明显 x0=y1,y0=x1-(a/b)*y1。
因此可以通过一个递归程序实现,对于每次递归 xn=xn+1,yn=xn+1-(a/b)*yn+1。
什么是扩展欧几里得?
考虑一个问题,如果我们知道a和b的最大公约数c,现在需要求出a*x+b*y=c的通解。这该怎么办?
不难看出通解形式一定是
x=x0+(b/c)*t,y=y0-(a/c)*t。那么该如何求出x0和y0?
首先不难看出x=1,y=0这一特解,我们要考虑的是能否通过这一特解推出结果。
根据欧几里得算法,再求gcd(a,b)时已经的出gcd(b,a%b),那么一定有b*x1+(a%b)*y1=c。
对与这一等式可以转化为:b*x1+(a-a/b*b)*y1=c ==> a*y1+b(x1-a/b*y1)=c。很明显 x0=y1,y0=x1-(a/b)*y1。
因此可以通过一个递归程序实现,对于每次递归 xn=xn+1,yn=xn+1-(a/b)*yn+1。
#include<stdio.h> #include<algorithm> #include<string.h> using namespace std; const int maxm = 100005; 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 n, i, j, k, sum, a, b, x, y; while (scanf("%d%d", &a, &b) != EOF) { k = e_gcd(a, b, x, y); printf("%d %d %d\n", k, x, y); } return 0; }
相关文章推荐
- zoj 3609 Modular Inverse 求最小逆元 裸的的扩展欧几里得
- codeforces Educational Codeforces Round 16 D. Two Arithmetic Progressions 扩展欧几里得
- pij2891 扩展欧几里得中国剩余定理
- 扩展欧几里得
- hdu 1576(数论之扩展欧几里得)
- POJ 2115 C Looooops [扩展欧几里得]【数论】[水]
- codeforces 612A The Text Splitting(扩展欧几里得)
- nyist 769 乘数密码(扩展欧几里得求逆元)
- 数论 + 扩展欧几里得 - SGU 106. The equation
- Strange Way to Express Integers (模线性方程组(扩展欧几里得))
- POJ 1091 跳蚤 数论-容斥原理、扩展欧几里得
- POJ 1061 青蛙的约会 扩展欧几里得
- 扩展欧几里得初学整合
- poj-青蛙的约会(扩展欧几里得)&&nyoj-小柯的约会
- codeforces724c Ray Tracing(扩展欧几里得)
- CodeForces 787A A. The Monster(扩展欧几里得)
- codeforces724C. Ray Tracing(扩展欧几里得详解)
- HDU1576 A/B(扩展欧几里得)
- 青蛙的约会(扩展欧几里得) POJ - 1061
- POJ 2115 扩展欧几里得解最基本的同余方程