扩展欧几里德!!!!!
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);
}
}
}
如何求解方程 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);
}
}
}
相关文章推荐
- Mate7微信指纹支付来了 比Touch ID整合微信早一点
- 研究生怎样进行良好的情绪管理
- 总结-html
- ls -l各个位置详解
- 实现医生工作站的辅助检查功能的代码(七)
- 一些关于jQuery的使用方法
- 总结-javascript
- 第三次实验报告
- PaintCode 教程:矢量图轻松转换成CoreGraphics代码
- lucene3.6.0 经典案例 入门教程
- K-means算法和矢量量化
- GDB调试器使用总结
- 六一儿童节就要过去了,您是否因为工作忙绿而没办法陪孩子玩
- setjmp和longjmp goto应用
- 安卓学习笔记
- spingMVC之国际化
- 血色西晋读书杂记
- Java正则表达式
- 贪心/数学 2015百度之星资格赛 1004 放盘子
- OPENCART 2.X 自适应主题模板 ABC-0629