您的位置:首页 > 其它

【hiho一下-95】 扩展欧几里得算法

2016-04-25 17:12 369 查看
      例题是hiho的一道题:

      题目

      这道题主要用到了欧几里得扩展算法,并且求一下最小正整数解就好了,没什么特别的。不过,再次学习了一下欧几里得扩展算法,有了更深的理解。欧几里得扩展算法可以有两种形式:

      1. ax + by = c = bx +(a%b)y 证明很容易,根据欧几里得算法,设t=(a,b),a=k1*t, b=k2*t, (a%b)=k3*t,那么c也能表示成t的倍数,只要修改x和y,就一定能相等。

      2. a*t1(k-1) + b*t2(k-1) = t3(k-1)

          a*t1(k) + b*t2(k) = t3(k)

          a*t1(k+1) + b*t2(k+1) = t3(k+1)

          t3(k+1) = t3(k-1)%t3(k)

      只要一直迭代下去,直到t3(k+1)=0,那么t3(k)就是最小公约数。有人可能会迷惑,这个公约数是谁和谁的呢?那么如果我们设置t3(0)=a,t3(1)=b,那么就是(a,b),由此可以得到最初的两个式子:

      a*1 + b*0 = a

      a*0 + b*1 = b

      只要推理一下,就能得到递推公式:

      t3(k+1) = t3(k-1) % t3(k)

      t1(k+1) = t1(k-1) - t1(k)*tmp

      t2(k+1) = t2(k-1) - t2(k)*tmp

      tmp = t3(k-1)/t3(k)

      证明方法请自行百度一下:证明

      下面是题目的代码:

//
//  hiho.cpp
//  hiho
//
//  Created by lhq on 16/4/25.
//  Copyright © 2016年 lhq. All rights reserved.
//

#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;

/*
ax + by = gcd = bx + a%by = bx + (a - a/b * b)y = ay + (x - a/b*y)b

v1 > v2
s1 + v1*t = s2+ v2*t - km
(v1-v2)*t + mk = s2 - s1

v2 > v1
s2 + v2*t = s1 + v1*t -km
(v2-v1)*t + km = s1 - s2

at + mk = gcd
求t,k   t,k > 0 且为整数

ax + by = gcd
a*(x + b/gcd * u)
b*(y - a/gcd * u)

求最小的x

*/

// ax + by = c  a = b , b = a%b 直到b = 0 主动改变a,b
long long gcd_ex(long long& x, long long& y, long long a, long long b){
if(b == 0){
x = 1;
y = 0;
return a;
}
long long tmp = gcd_ex(x, y, b, a%b);
long long tmpy = y;
y = x - (a/b)*y;
x = tmpy;
return tmp;
}

// at1 + bt2 = t3   t3 = t1%t2 直到t3=1 主动改变x,y  注意:初始值设置为,t3(k-1)=a, t3(k)=b,所以肯定能得到t3=(a,b)
long long gcd_ex_2(long long& x, long long& y, long long a, long long b){
long long to_1,to_2,to_3;
long long tm_1,tm_2,tm_3;
long long tn_1,tn_2,tn_3;
//不存在最大公约数
if(a == 0 || b == 0){
x = y = 0;
return 0;
}
to_1 = 1; to_2 = 0; to_3 = a;
tm_1 = 0; tm_2 = 1; tm_3 = b;
for(tn_3 = to_3%tm_3; tn_3!=0; tn_3=to_3%tm_3){
long long tmp = to_3 / tm_3;
tn_1 = to_1 - tmp * tm_1;
tn_2 = to_2 - tmp * tm_2;

to_1 = tm_1; to_2 = tm_2; to_3 = tm_3;
tm_1 = tn_1; tm_2 = tn_2; tm_3 = tn_3;
}
x = (tm_1%(b/tm_3) + b/tm_3)%(b/tm_3);   //最小正整数解
y = (tm_2%(b/tm_3) + a/tm_3)%(a/tm_3);   //最小正整数解
return tm_3;
}

int main(){
long long s1,s2,v1,v2,m;
long long x,y,a,b,c,gcd;
while(cin>>s1>>s2>>v1>>v2>>m){
a = (v1 - v2);
b = m;
c = (s2 - s1);
if(a<0){
a = -a; c = -c;
}
if(c<0){
c += m;
}
gcd = gcd_ex_2(x, y, a, b);
//        gcd = gcd_ex(x, y, a, b);
if(c % gcd){
cout<<-1<<endl;
}else{
b = b/gcd;
x = (x*c/gcd)%b;
if(x>0){
cout<<x<<endl;
}else{
while(x<0){
x += b;
}
cout<<x<<endl;
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: