您的位置:首页 > 其它

扩展欧几里德!!!!!

2015-06-01 19:31 288 查看
扩展欧几里德:

如何求解方程 ax + by = c 的整数解?

先 求 ax + by = gcd(a,b) 的整数解x0,y0 , 从而得到 原方程 的特解 为 x = x0 * c / gcd(a,b) ; y = y0 * c / gcd(a,b) ;

所以主要求的是 ax + by = gcd(a,b) 这个方程的整数解。

已知知 gcd( a , b) = gcd( b , a%b );

和求最大公约差不多 这里也用递归来求

状态A :a1 * x1 + b1*y1 =gcd( a1 , b1)

状态B:a2 * x2 + b2*y2 =gcd( a2 , b2)

这是 递归 过程中的 连续两个过程,其中 a2 = b1 ; b2 = a1%b1 ;

( 假设 A 为前一个状态 , 即在 过程 A 中 调用 过程B 。 )

先求出 B 的解 ,再推导出 A 的解 :

对于状态 B ,它可以化成 :

a2 * x2 + b2 * y2 = b1 * x2 + (a1%b1) * y2

= b1 * x2 + (a1 - k*b1) * y2 // k = (int) a1 / b1

= a1 * y2 + b1 * (x2 - k * y2)

= gcd( a2 , b2 )

= gcd( a1 , b1 )

= a1 * x1 + b1*y1

便可以求出 方程 A 的特解 为 x1 = y2 ; y1 = x2 - k * y2; // k = (int) a1 / b1

已经知道 怎么由下一层方程的解 推出 上一层的解 , 下面代码还会展示递归结束怎么处理。

递归代码:

void ext_ou ( int a, int b, int &x, int &y) {

if(b==0) { // 表示递归结束,此时 状态 为 : a * x + 0 * y = a ; 所以 x = 1;而 y 可以取任意值 但最好取0 因为其他值可能使最后结果超出 int 范围(个人观点)

x = 1;

y = 0;

return;

}

ext_ou(b,a%b,x,y);

int x0 = x;

int y0 = y;

x = y0;

y = x0 - ( a / b ) * y0 ;

return;

}

练习:POJ 1061 青蛙的约会

直接上代码 :

#include<cstdio>

using namespace std;

long long gcd(long long a,long long b){

if(b==0) return a;

return gcd(b,a%b);

}

void ext_ou(long long a,long long b,long long &x,long long &y){

if(b==0) {

x = 1;

y = 0;

return;

}

ext_ou(b,a%b,x,y);

long long x0=x;

long long y0=y;

x = y0;

y = x0-(a/b)*y0;

return;

}

int main(){

long long x,y,m,n,l,k1,k2,g;

while(scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l)!=EOF) {

ext_ou(n-m,l,k1,k2);

g = gcd(n-m,l);

k1 = k1*(x-y);

k2 = k2*(x-y);

if(k1%g!=0||k2%g!=0) {

printf("Impossible\n");

}

else {

k1/=g;

k2/=g;

if(k1<0) {

int k = -k1/l;

k1+=(k*l+l);

}

k1 = k1%l;

printf("%lld\n",k1);

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: