zoukankan      html  css  js  c++  java
  • 浅谈扩展欧几里得[exgcd] By cellur925

    关于扩展欧几里得从寒假时就很迷,题解过了同余方程,但是原理并不理解。

    今天终于把坑填上了qwq。

    由于本人太菜,不会用markdown,所以这篇总结是手写的(什么)。(字丑不要嫌弃嘛)

    ********Update9.28**********

     刚刚我们求出的是一组特值,那么如何求通值?

    约定:设x0,y0为一组特解,t为任意整数,设a>b(不行再交换)

    那么有  x=x0+b/gcd*t
         y=y0-a/gcd*t

    *******************************

    奉上三道例题:

    Ep1 青蛙的约会 Luogu P1516

    花姐姐(@皎月半洒花)说的太棒了,我都不忍再去添加什么。

    奉上链接,侵删!

    Code

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cmath>
     4 
     5 using namespace std;
     6 typedef long long ll;
     7 
     8 ll xx,yy,ans;
     9 ll x,y,m,n,t;
    10 
    11 ll exgcd(ll a,ll b,ll &xx,ll &yy)
    12 {
    13     if(!b)
    14     {
    15         xx=1;
    16         yy=0;
    17         return a;
    18     }
    19     ans=exgcd(b,a%b,xx,yy);
    20     ll tmp=xx;
    21     xx=yy;
    22     yy=tmp-a/b*yy;
    23     return ans;
    24 }
    25 
    26 int main()
    27 {
    28     scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&t);
    29     ll a=n-m,z=x-y;
    30     if(a<0) a=-a,z=-z;
    31     exgcd(a,t,xx,yy);
    32     if(z%ans) printf("Impossible");
    33     else printf("%lld",((xx*(z/ans))%(t/ans)+(t/ans))%(t/ans));
    34     return 0;
    35 }
    View Code

    注意体会同余方程转线性方程的思想与做法!

    Ep2 倒酒 Luogu P1292

    容易看出,得到酒的最小体积是gcd(a,b),这种思想在我以前写的“瓶子和燃料”一题中有所体现。模拟一下就可以发现,之后的次数就是ax+by=gcd(a,b)的一组最小解。

    套exgcd板子就行了,但是注意取最小值的那一部分,其实感觉每个题取最小值的方法都各有千秋,都要独立思考,这是关键。

    一个不错的题解,侵删。

    Code

     1 #include<cstdio>
     2 #include<algorithm>
     3 
     4 using namespace std;
     5 typedef long long ll ;
     6 
     7 ll a,b,x,y,ans;
     8 
     9 ll exgcd(ll a,ll b,ll &x,ll &y)
    10 {
    11     if(!b)
    12     {
    13         x=1;y=0;
    14         return a;
    15     }
    16     ll d=exgcd(b,a%b,x,y);
    17     ll tmp=x;
    18     x=y;
    19     y=tmp-y*(a/b);
    20     return d;
    21 }
    22 
    23 int main()
    24 {
    25     scanf("%lld%lld",&a,&b);
    26     ans=exgcd(a,b,x,y);
    27     printf("%lld
    ",ans);
    28     a/=ans,b/=ans;
    29     while(x>0) x-=b,y+=a;
    30     while(x+b<=0&&y>=a) x+=b,y-=a;
    31     printf("%lld %lld",-x,y);
    32     return 0;
    33 }
    View Code

    ps:while(x>0)那里如果写成while(x)竟会死循环,还是老实一点吧。

    Ep3 同余方程 Luogu P1082

    把同余方程转一下。直接套exgcd模板,取最小值部分,lyd老师的讲解:

    “用exgcd求出一组特解x0,y0,则x0就是原方程的一个解,通解为所有膜b与x0同余的整数,通过取模操作把解的范围移动到1~b”之间,就得到了最小正整数解。

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 using namespace std;
     6 int exgcd(int a,int b,int &x,int &y)
     7 {
     8     if(b==0)  
     9     {  
    10           x=1;  
    11           y=0;  
    12           return a;  
    13     }  
    14     int r=exgcd(b,a%b,x,y);  
    15     int t=x;  
    16     x=y;  
    17     y=t-a/b*y;  
    18     return r;  
    19 
    20 }
    21 int main()
    22 {
    23     int a,b,x,y;
    24     scanf("%d%d",&a,&b);
    25     exgcd(a,b,x,y);
    26     cout<<(x+b)%b;
    27     return 0;
    28 } 
    View Code
  • 相关阅读:
    2015多校1006.First One
    2015多校.MZL's endless loop(欧拉回路的机智应用 || 构造)
    LUXURY 8
    矩阵快速幂模板
    博弈入门
    cf558c(bfs)
    LUXURY 7
    dfs序 + RMQ = LCA
    双端队列
    UVa-401 Palindromes
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9514767.html
Copyright © 2011-2022 走看看