看(ACM-ICPC程序设计系列)《数论及应用》第一章,讲到扩展欧几里德算法时,讲到POJ上的一个题目:POJ1061,看了很久也没看懂,可能是数学基础太差了吧!

还好的是我把不懂的地方跳过去了,看到第三章讲同余问题,再次回忆起扩展欧几里德算法了。这次绕不过去了!

首先不懂的就是:a*x ≡ b (mod m) 与ax+my=b的转化。

后来,慢慢看着,觉得应该是这样的:设d=(a*x)%m ;(a*x-d)/m=k1 , (b-d)/m=k2 ;很容易得到这样的等式:a*x-k1*m=b-k2*m,即a*x+(k2-k1)*m=b; 于是,只要设y=k2-k1,就可以得到:ax+my=b这样的二元一次不定方程了。这样一元线性同余方程就转化成了二元一次不等式了!

第二个不懂的就是如何运用扩展欧几里德算法来求任意二元一次不定方程的解。

为了化简问题,我从最简单的地方开始把思路整理一遍。扩展欧几里德算法最原始的形态是这样的:设a,b不全为0,则存在整数x和y,使得:gcd(a,b)=ax+by。 其实这里有一个要求需要注意:gcd(a,b)=1。例如:a=4,b=3,则存在:x=1,y=-1,满足:gcd(a,b)=1=ax+by。假如gcd(a,b)=K怎么求呢?我觉得可以这样做,设x0=x/k,y0=y/k;则ax0+by0=1,求得x0=1,y0=-1,那么实际上,x=k*x0,y=k*y0。例如:a=4,b=3,k=3。则方程为:4x+3y=3。按照上面的思路:很容易得到一个解:x=3,y=-3。

好了,现在到最核心的问题:扩展欧几里德算法内部是怎么运行的?这里也是我为之心碎了好久的地方!

为了更容易理解,还是先举例让自己有个形象的感觉吧!例如:a=225,b=21,则gcd(a,b)=3。那么,这个3如何用225和21的线性组合表示呢?也就是说:225*x+21*y=3,x,y的值可以是多少呢?

我们先来追踪一下用欧几里德算法求225与21的的最大公约数3的过程。225=21*10+15;21=15*1+6;15=2*6+3;6=2*3+0;这几个式子代表了这样的过程:gcd(225,21)=gcd(21,15)=gcd(15,6)!我们再反推过来:gcd(225,21)=3=15-2*6=225-(21*10)-2*(21-15)=225-(21*10)-2*(21-225+21*10)=3*225-32*21;即x=3,y=-32。现在摆在我面前的问题就是怎么用程序实现这个过程了!

  1. int extend_gcd(int a,int b,int &x,int &y){
  2. if(b==0){
  3. x=1;y=0;
  4. return a;
  5. }
  6. int gcd=extend_gcd(b,a%b,x,y);
  7. int temp=x-a/b*y;
  8. x=y;
  9. y=temp;
  10. return gcd;
  11. }

这个程序实现的功能就是计算ax+by=gcd(a,b)这样的二元一次不定方程。

最后再来看看poj1061这道题的分析过程吧!

设青蛙一共跳了t步,如果我们把这段路拉成一条直线,则青蛙A离原点:x+m*t;青蛙B离原点:y+n*t:则会有:x+m*t-y-n*t=p*L(p是不定的)!即有:t*(n-m)+p*L=x-y

转化一下,设a=n-m,b=L,c=x-y,则有:a*t+b*p=c,即以t和p为变量的二元一次不定方程。

接下来就是解这个方程了!根据相关的定理:如果c%gcd(a,b)==0,则不定方程有整数解。

由于a*t+b*p=c不一定会满足gcd(a,b)=1,所以需要把方程变形。只需要把方程两边都同时除以gcd(a,b)就可以使新的方程系数满足gcd(a,b)=1,就可以用扩展欧几里德算法来解决问题了!

由于用扩展欧几里德算法计算出的来的x是:ax+by=1的结果,而我们的不定方程是ax+by=c,故x需要赋新的值x=x*c; 很让人烦的是计算到这里还不是最后的结果,因我们求的是最小正整数x,而我们刚才计算出来的不一定是最小值,所以需要这样处理:x=(x%b+b)%b,这样就能保证x是最小的正整数了!

补充一点的是:ax+by=c,最后的结果不只一个,而是一组:x,x+b,x+2*b,…x+(d-1)*b;.

下面把代码贴出来吧!

  1. #include<stdio.h>
  2. typedef long long ll;
  3. ll gcd(ll a,ll b){
  4. return !b?a:gcd(b,a%b);
  5. }
  6. ll  extend_gcd(ll m,ll n,ll &x,ll &y){
  7. if(n==0){
  8. x=1;y=0;
  9. return m;
  10. }else{
  11. ll g = extend_gcd(n,m%n,x,y);
  12. ll t=x-m/n*y;
  13. x=y;y=t;
  14. return g;
  15. }
  16. }
  17. int main(){
  18. ll a,b,c,x,y,d;
  19. ll sx,sy,m,n,L;
  20. while(~scanf("%I64d %I64d %I64d %I64d %I64d",&sx,&sy,&m,&n,&L)){
  21. a=n-m;
  22. b=L;
  23. c=sx-sy;
  24. d=gcd(a,b);
  25. if(c%d==0){
  26. a=a/d;
  27. b=b/d;
  28. c=c/d;
  29. extend_gcd(a,b,x,y);
  30. x=c*x;
  31. x=(x%b+b)%b;
  32. printf("%I64d\n",x);
  33. }else{
  34. printf("Impossible\n");
  35. }
  36. }
  37. return 0;
  38. }

我个人觉得,代码这样是最容易理解的!

参考博客:

http://blog.csdn.net/zjsxzjb/article/details/6262667

http://huangzhenbc.blog.163.com/blog/static/17997828220112512028548/

数论学习之(一):一元线性同余方程和二元一次不等式相关推荐

  1. 【数论】同余(四):一元线性同余方程组(两两相消、中国剩余定理)

    同余问题共7part,我的博客链接: 基本概念与性质 逆元:概念.求解方法与推导 线性同余方程 一元线性同余方程 一元线性同余方程组 多元线性同余方程 高次同余方程:BSGS算法(大小步算法.拔山盖世 ...

  2. flare-on 7 break第三部分求解:一元线性同余方程

    思考的结论:其实这种国际性的逆向比赛,肯定会考一些数学的知识,这个考的是比较基础了,无奈自己没有这个基础. 话说还是flare 7的break这道题,到了最后,第三步验证,函数竟然来到了0x08053 ...

  3. POJ 2115C Looooops[一元线性同余方程]

    一元线性同余方程 定义: $a$,$b$是整数,$m$是正整数,形如 $ax\equiv b\,(mod\, m)$ 且$x$是未知数的同余式称作一元线性同余方程. 对于方程$ax\equiv b\, ...

  4. POJ2891——Strange Way to Express Integers(一元线性同余方程组)

    由若干个一元线性同余方程组构成的方程组,叫做一元线同余方程组. 求解 我们可以将其统一划成a*x ≡ b(mod m)的形式,这样有利于算法的实现. 对于同于方程组的求解,其实质过程就是对于其中的同余 ...

  5. 解一元线性同余方程组(详解+例题)

    问题描述:给出bi,ni的值,且n1, n2, n3,-, ni两两之间不一定互质,求Res的值? 解:采用的是合并方程的做法. 这里将以合并第一第二个方程为例进行说明 由上图前2个方程得(设k1.k ...

  6. 线性同余方程和中国剩余定理学习笔记

    线性同余方程介绍 形如 a x ≡ c ( m o d b ) ax \equiv c \pmod b ax≡c(modb) 的方程被称为 线性同余方程(Congruence Equation). 求 ...

  7. 【数论】同余(五):多元线性同余方程

    同余问题共7part,我的博客链接: 基本概念与性质 逆元:概念.求解方法与推导 线性同余方程 一元线性同余方程 一元线性同余方程组 多元线性同余方程 高次同余方程:BSGS算法(大小步算法.拔山盖世 ...

  8. 线性不定方程与线性同余方程

    线性不定方程解法 扩展欧几里得算法: 考虑求这个不定方程的一个解: ax+by=c 可以证明该不定方程有解的充分必要条件是(a,b) | c. 证明:(a,b) | a且(a,b) | b,因为c=a ...

  9. 【专题】线性同余方程

    定义:a,b是整数,形如 ax≡b(mod m) ax\equiv b(mod \ m),且x是未知整数的同余式称为一元线性同余方程. 定理:a,b,m是整数且m>0, gcd(a,m)=d g ...

最新文章

  1. CMU创建一个开源的AI代码生成模型,C语言表现优于Codex
  2. Spring JDBC整合
  3. python高维向量的可视化_Tensorboard教程:高维向量可视化
  4. eclipse官网下载详细指南
  5. maven(6)仓库
  6. java怎样生成32位全是整形的主键_用java生成32位全球唯一的id编号
  7. Python刷题-6
  8. cv2不能读取中文路径
  9. 字段、数据库表-三大范式及存储方式-by小雨
  10. Android 自定义一个简版的取色器ColorPicker
  11. FastDFS原理及维护
  12. 三菱 PLC ST语言 步进电机正反转
  13. MySQL: 为什么使用 innobackupex 备份恢复搭建主从时,必须人为设置 gtid_purged 变量
  14. 腾讯认证QQ空间秒升级为专业版方法!
  15. Linux 常用命令 Updating
  16. 佳能扫描仪按下按钮后自动打开phtoshop怎么办
  17. 什么是HashTable?HashMap和HashTable的区别
  18. mca允许安装任何来源
  19. PhotoMOS输出光电耦合器的概要
  20. 时域同步平均(TSA)降噪原理

热门文章

  1. Java语言基础知识(一)
  2. 改善睡眠失眠10大方法,让你失眠一招入睡
  3. iOS 手机淘宝 自动创建一个人的群聊 实现源码 hook 代码源码
  4. 从开发角度读懂公司卫生间一直有人窜稀的原理
  5. 磁盘分区、格式化及 LVM 管理
  6. 这款 SQL自动检查神器,吊炸天的功能,真TMD多!!
  7. php手册下载后打开没有内容,word保存后内容不见了怎么办
  8. 2018-05-18 docker supervisord进程管家
  9. [附源码]计算机毕业设计Node.js-报刊征订管理系统(程序+LW)
  10. Antd组件库的使用