• gcd(欧几里得算法)与exgcd(扩展欧几里得算法)


    欧几里得算法:

    1.定义:gcd的意思是最大公约数,通常用扩展欧几里得算法求

    原理:gcd(a, b)=gcd(b, a%b)

    2.证明:

    令d=gcd(a, b)  =>  a=m*d,b=n*d

    则m*d=t*n*d+a%b  =>  a%b=d*(m-t*n)

    gcd(b, a%b)=gcd(n*d, (m-t*n)*d)

    令gcd(n, m-t*n)=e  =>  n=x*e,m-t*n=y*e

    则m-x*e*n=y*e  =>  m=e*(x*n+y)

    由gcd(n, m)=1知gcd(e*(x*n+y), e*x)=1

    故e=1

    故gcd(n*d, (m-t*n)*d)=d即gcd(b, a%b)=gcd(a, b)

    3.边界:

    当b=0时return a

    可以视为gcd(a, 0)=a,任何数都能整除0

    也可以视为gcd(a, b)=b,这里的a和b是上一层的,满足a%b=0

    4.特殊情况:
    当a<b时,a%b=a,所以在下一层gcd(b, a%b)中相当于把a与b交换

    5.代码:

    1 int gcd(int a,int b){  return b ? gcd(b,a%b) : a;}
    一行gcd

    扩展欧几里得算法:

    1.丢番图方程:

    有一个或者几个变量的整系数方程,它们的求解仅仅在整数范围内进行。

    扩展欧几里得算法研究的是形如 a*x+b*y=c 的丢番图方程的解

    2.裴蜀定理:

    对于正整数a和b,令gcd(a, b)=d,则对于任意整数x和y,都有d|(a*x+b*y)

    证明:

    令a=n*d,b=m*d,则a*x+b*y=d*n*x+d*m*y

    显然d|(d*n*x+d*m*y)

    3.引理:

    丢番图方程 a*x+b*y=c 有解当且仅当d|c

    对于任意整数x和y,a*x+b*y的最小正值为gcd(a, b)

    证明:

    ①必要性:

    由裴蜀定理,不存在整数x和y,使得d不整除(a*x+b*y)

    ②充分性:

    要证a*x+b*y=c有解,只需a*x+b*y=d有解

    令对于任意整数x和y,a*x+b*y能得到的最小正值为s

    由裴蜀定理,d|s,则d<=s

    令q=⌊a/s⌋,p=a%s

    则p=a-q*(a*x+b*y)=a*(1-q*x)-q*b*y=a*(1-q*x)+b*(-q*y)

    由p=a%s知0<=p<s

    又s为a*x+b*y能得到的最小正值

    故p=0,即s|a

    同理,s|b,即s|d,故s<=d

    综上,s=d

    即对于任意整数x和y,a*x+b*y能得到的最小正值为d

    故存在整数x和y,使a*x+b*y=d

    即存在整数x和y,使a*x+b*y=c

     4.扩展欧几里得算法:

    通常将求解a*x+b*y=c转化为求解a*x+b*y=gcd(a, b),得解后乘上c/gcd(a, b)即可


    a*x1+b*y1=gcd(a, b)

    b*x2+(a%b)*y2=gcd(b, a%b)

    由gcd(a,b)=gcd(b,a%b)知

    a*x1+b*y1=b*x2+(a%b)*y2

    =b*x2+(a-b*⌊a/b⌋)*y2=a*y2+b*(x2-⌊a/b⌋*y2)

    故x1=y2,y1=(x2-⌊a/b⌋*y2)

    如此递归直至边界情况

    5.边界:

    当b=0时,gcd(a, b)=a(任何数都能整除0)

    a*x+b*y=a*x=gcd(a, b)*x

    若使a*x+b*y=gcd(a, b),只需x=1,y可以为任何值,通常设为0,减少溢出的风险

    y的多值对应方程的多解

    6.通解:

    对于对于第一个解x0和y0,其他解可以表示为x0+(b/d)*k和y0-(a/d)*k

    推导:

    令a*(x+m)+b*(x-n)=d

    =>  a*m=b*n  => m/n=b/a

    因gcd(a, b)=d,m和n均为整数

    故m和n的最小值分别为b/d和a/d

    若要求其中一个解为正整数,可在得到负解后用通解转化为正数

    7.代码:

    1 void exgcd(int a,int b,int &x,int &y){
    2     if(!b){
    3         x=1,y=0;
    4         return ;
    5     }
    6     exgcd(b,a%b,x,y);
    7     int z=x;
    8     x=y,y=(z-a/b*y);
    9 }
    View Code

    8.易错点:

    算法中存在乘法,有溢出的风险,应见机开long long

    例题:

    洛谷4549 裴蜀定理

    洛谷1516 青蛙的约会 

    洛谷3951 小凯的疑惑

    洛谷1082 同余方程

  • 相关阅读:
    ue父子组件的数据传递示例
    vue.js 组件之间传递数据
    Vue2.0子同级组件之间数据交互
    assets 和static的区别
    Vue中src属性绑定的问题
    css3设置背景图片的大小
    如何在HTML中插入空格
    css背景图片的设置
    vue动态组件 互相之间传输数据 和指令的定义
    webservice的优缺点
  • 原文地址:https://www.cnblogs.com/cdcq/p/11366100.html
Copyright © 2020-2023  润新知