【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)
证明方法请自行百度一下:证明
下面是题目的代码:
题目
这道题主要用到了欧几里得扩展算法,并且求一下最小正整数解就好了,没什么特别的。不过,再次学习了一下欧几里得扩展算法,有了更深的理解。欧几里得扩展算法可以有两种形式:
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; }
相关文章推荐
- android解决无法设定listview的item高度
- 【AudioProfile】情景模式下音效的默认设置
- python的setdefault方法
- 滑动效果的View
- javascript 实现继承的几种方式
- 坑爹的oracle11g新特性 密码延迟验证
- ToString()的浅显解释(转)
- 为自己的本地站点封装域名
- 用数组实现线性表
- viewWillDisappear,viewWillAppear不调用的解决方法
- 可执行jar包
- TransMac 下载 win7 win10 U盘启动的制作方法 win7 win10 U盘启动的 transMac制作方法
- hdu 5661 异或
- 连八进制都不知道
- 【剑指offer-Java版】03二维数组中的查找
- ThreadLocal in java
- ruby 除法运算
- jQuery网页右侧固定层显示隐藏在线qq客服代码
- JavaScript基础学习(一)—JavaScript简介
- iOS开发——点击图片全屏显示