什么是GCD

GCD是最大公约数的简称(当然理解为我们伟大的党也未尝不可)。在开头,我们先下几个定义:
①a|b表示a能整除b(a是b的约数)
②a mod b表示a-[a/b]b([a/b]在Pascal中相当于a div b)
③gcd(a,b)表示a和b的最大公约数
④a和b的线性组合表示ax+by(x,y为整数)。我们有:若d|a且d|b,则d|ax+by(这很重要!)

线性组合与GCD
现在我们证明一个重要的定理:gcd(a,b)是a和b的最小的正线性组合。
证明:
设gcd(a,b)为d,a和b的最小的正线性组合为s
∵d|a且d|b,
∴d|s。
而a mod s=a-[a/s]s
         =a-[a/s](ax+by)
         =a(1-[a/s]x)-b[a/s]y
亦为a和b的线性组合
∵a mod s<s,a mod s不能是a和b的最小的正线性组合
∴a mod s=0,即s|a
同理由s|b
∴s为a,b的公约数
∴s<=d
∵d|s
∴d=s。证毕。

由这条定理易推知:若d|a且d|b,则d|gcd(a,b)

扩展欧几里得是对于一对整数a,b总可以找到一组解x,y使ax+by=gcd(a,b)

例如a=6,b=15时,gcd(a,b)=3;一组可行的解是x=3,y=-1,当然还有其他解如x=-2,y=1.

给出实现程序

 int exGcd(int a,int b,int &d,int &x,int &y)//d表示gcd(a,b)
{
if(!b){d=a;x=;y=;}
else {exGcd(b,a%b,d,y,x);y-=x*(a/b);}
}

我们说过,gcd(a,b)可以表示为a和b的最小的正线性组合。现在我们就要求这个最小的正线性组合ax+by中的x和y。

从最简单的情况开始。当b=0时,我们取x=1,y=0。当b≠0时呢?
假设gcd(a,b)=d,则gcd(b,a
mod b)=d。若我们已经求出了gcd(b,a mod b)的线性组合表示bx'+(a mod b)y',则
gcd(a,b)=d
        =bx'+(a mod b)y'
        =bx'+(a-[a/b]b)y'

=ay'+b(x'-[a/b]y')=d=ax+by

那么,x=y',y=x'-[a/b]y'。这样就可以在Euclid的递归过程中求出x和y。

所以在上述代码的第4行中:

    x=y';(即x与y交换)

    (交换前)y=x'-(a/b)*y';

    (交换后)y=y'-(a/b)*x';

  所以递归时

    exGcd(b,a%b,d,y,x);交换了x,y
    y-=x*(a/b);//更新了y


求出了一组解肯定远远不够,如何求出其他解呢?一个公式就可以解决,对于方程的一个解(x0,y0)它的任意整数解可以表示为

  (x+ k*(b/d),y- k*(a/d))

推导过程为:
  设(x1,y1)为方程的一组已知解,(x2,y2)为一组未知解,代入方程后得:

  a*x1+b*y1=d;

  a*x2+b*y2=d;

  a*x1+b*y1=a*x2+b*y2

  移项得:

  a*(x1-x2)=b*(y1-y2)

  两边同时除以d(令a'=a/d,b'=b/d)

  a'*(x1-x2)=b'*(y1-y2)

  a' 与 b' 一定互质

  (x1-x2)一定可以被b整除

  设x1-x2=k*b'

  a'*k*b'=b'*(y1-y2)

  k*a'=y1-y2

  所以x2=x1-k*b'

    y2=y1+k*a'


同余方程:aΞb(mod n)表示(a mod n)==(b mod n)即a-b可以被n整除(注意是整除);

所以可以设ax-b为n的正整数倍,所以又可以设ax-b为n的y倍;

得到ax-b==ny变形得ax-ny==b;

这下就可以用扩展欧几里得解决了!

相关的例题在Vijos P1781 同余方程,2012年提高组的题,如果知道了这个方程,那AC简直妥妥的!下面是AC代码

 /*
ID: ringxu97
LANG: C++
TASK: NOIp2012-同余方程
SOLUTION: 扩展欧几里得 同余方程的解法
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
int exgcd(int a,int b,int &d,int &x,int &y)
{
if(!b){d=a;x=;y=;}
else {exgcd(b,a%b,d,y,x);y-=x*(a/b);}
}
int main()
{
int a,b;
scanf("%d%d",&a,&b);
int g,x,y;
exgcd(a,b,g,x,y);
int ans=x;
while(ans<)ans+=b/g;
printf("%d\n",ans);
return ;
}

【数学】【NOIp2012】同余方程 题解 以及 关于扩展欧几里得与同余方程的更多相关文章

  1. poj 1061 扩展欧几里得解同余方程(求最小非负整数解)

    题目可以转化成求关于t的同余方程的最小非负数解: x+m*t≡y+n*t (mod L) 该方程又可以转化成: k*L+(n-m)*t=x-y 利用扩展欧几里得可以解决这个问题: eg:对于方程ax+ ...

  2. 扩展欧几里得求解同余方程(poj 1061)

    设方程 ax + by = c , 若 gcd(a,b) 是 c的因子(记作gcd(a,b)|c)则方程有解,反之无解. 其中x0,y0是方程的一组特解 , d = gcd(a,b), poj1061 ...

  3. 【扩展欧几里得】NOIP2012同余方程

    题目描述 求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解. 输入输出格式 输入格式: 输入只有一行,包含两个正整数 a, b,用一个空格隔开. 输出格式: 输出只有一行,包含一个正 ...

  4. [P1082][NOIP2012] 同余方程 (扩展欧几里得/乘法逆元)

    最近想学数论 刚好今天(初赛上午)智推了一个数论题 我屁颠屁颠地去学了乘法逆元 然后水掉了P3811 和 P2613 (zcy吊打集训队!)(逃 然后才开始做这题. 乘法逆元 乘法逆元的思路大致就是a ...

  5. 【Luogu】P1516青蛙的约会(线性同余方程,扩展欧几里得)

    题目链接 定理:对于方程\(ax+by=c\),等价于\(a*x=c(mod b)\),有整数解的充分必要条件是c是gcd(a,b)的整数倍. ——信息学奥赛之数学一本通 避免侵权.哈哈. 两只青蛙跳 ...

  6. interesting Integers(数学暴力||数论扩展欧几里得)

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAwwAAAHwCAIAAACE0n9nAAAgAElEQVR4nOydfUBT1f/Hbw9202m0r8

  7. POJ2115 - C Looooops(扩展欧几里得)

    题目大意 求同余方程Cx≡B-A(2^k)的最小正整数解 题解 可以转化为Cx-(2^k)y=B-A,然后用扩展欧几里得解出即可... 代码: #include <iostream> us ...

  8. EXGCD 扩展欧几里得

    推荐:https://www.zybuluo.com/samzhang/note/541890 扩展欧几里得,就是求出来ax+by=gcd(x,y)的x,y 为什么有解? 根据裴蜀定理,存在u,v使得 ...

  9. 浅谈扩展欧几里得[exgcd] By cellur925

    关于扩展欧几里得从寒假时就很迷,抄题解过了同余方程,但是原理并不理解. 今天终于把坑填上了qwq. 由于本人太菜,不会用markdown,所以这篇总结是手写的(什么).(字丑不要嫌弃嘛) ****** ...

随机推荐

  1. Objective-C和C++的区别

    1.都是有C语言延伸而来2.OC是完全动态的,C++是部分动态的3.OC不支持多继承,通过代理 类别 协议优雅的实现了相关的一系列特性4.调用机制不同OC里面叫发送消息  C++叫做调用函数数5.OC ...

  2. JS入门笔记

    DOM有四种节点: 1. 元素节点:即标签2. 属性节点:写在标签里的属性3. 文本节点:嵌在元素节点里展示出来的文本4. 文档节点:document 获取元素节点的三种常用方法: 1.ById 2. ...

  3. Javascript的AMD规范

    Javascript发展到今天,已经从一个小丑语言变成了不可替代的前端利器,已经脱离了低端的玩笑脚步,而转变为有规可依的强大语言. 本文主要讲述下如今被大力推广的AMD规范,为什么要AMD,什么场景是 ...

  4. java_设计模式_模板方法模式_Template Method Pattern(2016-08-11)

    定义: 定义一个操作中算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤.这里的算法的结构,可以理解为你根据需求设计出来的业务流程.特定的步骤就是指那些 ...

  5. cocos2dx JAVA,C++互相调用函数

    C++调用JAVA 例子 #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #include "platform/android/jni/Jni ...

  6. 自动化工具word文档批量转html

    企业有很多的科室,科室的每个人或多或少都会写一些文档,有些文档领导需要浏览,解决的办法是将编辑的文档打印出来,供领导浏览,或是为了节约企业成本,文档就在人与人这间或部门之间copy过来,copy过去. ...

  7. .net软件工程师面试题(参考答案)

    一.填空题(每空1分,共12分) 1面向对象的语言具有__封装______性.__继承_______性.__多态______性. 2能用foreach遍历访问的对象需要实现 ____Ienumerab ...

  8. php报警:Strict Standards: Only variables should be passed by reference in

    错误原因 因为end函数的原因. end函数: mixed end    ( array &$array   ) 你可以看到end的参数是一个引用(reference),而你只能把一个变量的引 ...

  9. 转:使用 Docker 搭建 Java Web 运行环境

    原文来自于:http://www.codeceo.com/article/docker-java-web-runtime.html Docker 是 2014 年最为火爆的技术之一,几乎所有的程序员都 ...

  10. 应用ubuntu(安装)

    U盘安装Ubuntu 12.04. 工具 UltraISO 9.6.1 ubuntu-12.04.3-desktop-i386 启动U盘 安装UltralISO,启动 文件—打开,选中下载的ubunt ...