zoukankan      html  css  js  c++  java
  • gcd+exgcd+例题(青蛙的约定)

    1.gcd的两种求法:

    一、更相减损法

    两个正整数$a$和$b$($a>b$),它们的最大公约数等于$a-b$的差值$c$和较小数$b$的最大公约数。

    1 int gcd(int a,int b)
    2 {
    3     if(a==b)
    4         return a;
    5     if(a>b)
    6         return gcd(a-b,b);
    7     if(a<b)
    8         return gcd(b-a,a);
    9 }

    二、辗转相除法

    两个正整数$a$和$b$($a>b$),它们的最大公约数等于$a$除以$b$的余数$c$和$b$之间的最大公约数。

    1 int gcd(int a,int b)
    2 {
    3     if(a%b==0)
    4         return b;
    5     else
    6         return gcd(a%b,b);
    7 }

    2.exgcd

    裴蜀定理:对于任意的整数$a$,$b$,都存在一对整数$x$,$y$,使得$ax+by=gcd(a,b)$成立。
    可以看出,这是一个递归求解的函数。在函数递归到最后的时候,存在$b=0$,不管$a$是什么,这时显然有一对整数$x=1$,$y=0$来使得:

    $a×1+0×0=gcd(a,0)$

    那么,我们通过这个递归的实现过程来进行回溯的模拟。当$b>0$ ,则程序还可以继续往下走:$gcd(b,a%b)=gcd(a,b)$。这时假设存在一对整数$x,y$ ,使得其一定会满足$b×x+(a%b)×y=gcd(b,a%b)$, 因为$a%b=a−b⌊a/b⌋ $,所以有以下的推导:$b×x+(a%b)×y=gcd(b,a%b)=bx+(a−b⌊a/b⌋)y=ay−b(x−⌊a/b⌋y)$这个时候令$x′=y,y′=x−⌊a/b⌋$,再结合一开始的原式子,就得出:$ax′+by′=gcd(a,b)$

    *裴蜀定理的应用:

                              $ax+by=exgcd(a,b)$

    那么可以推出:如果一个数$m$满足:$ax+by=m$,那么这个$m$一定是$gcd(a,b)$的倍数。
    那么对于一个经典方程$ax+by=1$,利用裴蜀定理,我们有:$gcd(a,b)=1$,即$a,b$一定互质。 

    扩展欧几里得算法

    在介绍扩展欧几里得算法之前,我想首先介绍它的应用:
    1、求解不定方程
    2、求解模的逆元
    3、求解线性同余方程
    为什么它能应用到这几个方面呢?回到裴蜀定理:$ax+by=m$
     对于这个不定方程,如果存在一组合法的解$(x,y)$,那么一定会有$gcd(a,b)|m$,即$m$是$gcd(a,b)$的倍数。那么现在我不仅想知道到底有没有解,而是想知道在有解的情况下,这个解到底是多少。

     

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

    *青蛙的约定

    • 设$x_0$为最终结果,让青蛙相对运动,可列
    出式子:
    • $(m - n)x_0 = y - x (mod L)$
    • 显然该式可以转化为:
    • $(m - n)x_0 + Ly = y - x$
    • 再变换一下变成:
    • $ax + by = c$

    • 变成了熟悉的$exgcd$问题,正常求解即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include <algorithm>
     4 #define ll long long 
     5 using namespace std;
     6 ll ans,x1,y1;
     7 ll exgcd(ll a,ll b,ll &x1, ll &y1)
     8 {
     9     if(!b)
    10     {
    11         x1=1;
    12         y1=0;
    13         return a;
    14     }
    15     ans=exgcd(b,a%b,x1,y1);
    16     ll t=x1;
    17     x1=y1;
    18     y1=t-a/b*y1;
    19     return ans;
    20 }
    21 
    22 int main()
    23 {
    24     ll n,m,x,y,l;
    25     cin>>x>>y>>m>>n>>l;
    26     ll b=n-m,a=x-y;
    27     if(b<0)
    28     {
    29         b=-b;
    30         a=-a;
    31     }
    32     exgcd(b,l,x1,y1);
    33     if(a%ans!=0)
    34         cout<<"Impossible";
    35     else
    36         cout<<((x1*(a/ans))%(l/ans)+(l/ans))%(l/ans);
    37 }

     

  • 相关阅读:
    [PA2014]Muzeum
    [TJOI2015]概率论
    To Do List
    【洛谷4172】 [WC2006]水管局长(LCT)
    HNOI2019退役记
    hdu 2159 FATE
    USACO 2019 January Contest, Platinum 题解
    luogu4774 [NOI2018]屠龙勇士
    NOI 2019游记
    loj #3145. 「APIO 2019」桥梁
  • 原文地址:https://www.cnblogs.com/very-beginning/p/12389345.html
Copyright © 2011-2022 走看看