zoukankan      html  css  js  c++  java
  • [数论][exgcd]同余方程

    题目描述

    求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解。

    输入

    输入只有一行,包含两个正整数 a, b,用一个空格隔开。

    输出

    输出只有一行,包含一个正整数 x0,即最小正整数解。输入数据保证一定有解。

    样例输入

    3 10
    

    样例输出

    7
    

    提示

    对于 100%的数据,2 ≤a, b≤ 2,000,000,000。

    思路:exgcd的应用——求解不定方程、求解线性同余方程

    -----------------------------------------------------------------------------

    下面给出关于ecgcd的详解与模板:(以下讨论的数全为整数)

    问题1:给出方程 ax+by=gcd(a,b) ,求解满足方程的x,y的一组解(求解不定方程)

    解:  构造一个相同形式的方程——bx1+(a%b)y1=gcd(b,a%b)

             联立上述两个方程:因为由欧几里得定理有gcd(a,b)=gcd(b,a%b),所以ax+by=bx1+(a%b)y1

            因为a%b=a-a/b*b,带入上式并整理得ax+by=ay1+b(x1-a/b*y1)

            对比等式左右两边得x=y1 , y=x1-a/b*y1 

            因此,若知道满足方程bx1+(a%b)y1=gcd(b,a%b)的x1,y1的一组解,就可以得出x,y的一组解

            同理关于方程bx1+(a%b)y1=gcd(b,a%b)的求解也可以用同样的方法由相应的x2,y2得出

            如此递归下去,当递归到最底层b=0时,显然方程的一组解为x=1,y=0

            得到这组解后,便可以回溯得到最顶层方程即ax+by=gcd(a,b)的一组解了。

    引理:存在 x , y 使得 ax+by=gcd(a,b)

    上述解法,我们可以用递归的方法来实现。

    void exgcd(ll a,ll b){//x,y为两参数,a,b为两参数的系数
      if(b==0) y=(x=1)-1;//x,y为全局变量
      else{
        exgcd(b,a%b);
        ll tmp=x;
        x=y;
        y=tmp-a/b*y;
      }
    }

    上述代码实现了求方程ax+by=gcd(a,b)的一组解x和y,可以由这一组解得到方程的其他多组解:(设x0,y0为一组已知解,x,y为通解)

    x=x0+b/gcd(a,b)*k

    y=y0+a/gcd(a,b)*k  (其中k为整数)

    将通解带入原方程即可验证。

    问题2:给出方程 ax+by=r,求解满足方程的x,y的一组解(求解不定方程)

    解: 当r%gcd(a,b)!=0时,方程无整数解

            当r%gcd(a,b)==0时,先利用exgcd求出方程ax+by=gcd(a,b)的一组解x0,y0,则有ax+by=r的一组解为x1=x0*r/c,y1=y0*r/c

            原方程的通解为  x=x1+b/gcd(a,b)*k

                                       y=y1+a/gcd(a,b)*k

    问题3:求关于 模方程 ax%b=c(ax=c(mod b))的解x(求解线性同余方程)

    解:方程转换为 ax+by=c ,即利用exgcd求不定方程的解x,y(最后只需要x的值)

     原方程的通解为x=x0+b/gcd(a,b)*k(其中x0为ax%b=c的其中一解)

    设s=b/gcd(a,b),则 x 的最小正整数解为 (x1%s+s)%s

    -----------------------------------------------------------------------------

    AC代码:

    #include <iostream>
    #include<cstdio>
    #define ll long long
    using namespace std;
    
    ll x,y;
    
    void exgcd(ll a,ll b){
      if(b==0) y=(x=1)-1;
      else{
        exgcd(b,a%b);
        ll tmp=x;
        x=y;
        y=tmp-a/b*y;
      }
    }
    
    int main()
    {
        ll a,b;
        scanf("%lld%lld",&a,&b);
        exgcd(a,b);
        while(x<=0) x+=b;
        printf("%lld
    ",x);
        return 0;
    }
    转载请注明出处:https://www.cnblogs.com/lllxq/
  • 相关阅读:
    POI中文API文档
    接口
    JDK中的URLConnection参数详解
    RPC远程过程调用概念及实现
    tkinter 打包成exe可执行文件
    PHP 的命令行模式
    php CLI SAPI 内置Web Server
    ppython的移位操作
    HAProxy基础
    HAProxy用法详解
  • 原文地址:https://www.cnblogs.com/lllxq/p/8613125.html
Copyright © 2011-2022 走看看