• 线性同余方程(扩展欧几里得应用)


    题目内容

    给定\(n\)组数据\(a_i, b_i, m_i\), 对于每组数据求出一个\(x_i\),使其满足\(a_i \times x_i \equiv b_i(mod \ m_i)\)

    如果无解则输出impossible

    输入格式

    第一行包含整数 \(n\),接下来\(n\)行,每行包含一组数据$ a_i, b_i, m_i$

    输出格式

    输出共\(n\)行, 每行数据输出一个整数表示一个满足条件的 \(x_i\),如果无解则输出 impossible

    每组数据结果占一行,结果可能不唯一,输出任意一个满足条件的结果均可。

    输出答案必须在\(int\) 范围之内

    数据范围

    \(1 \le n \le 10^5\)

    \(1 \le a_i,b_i,m_i \le 2 \times 10^9\)

    输入样例

    2
    2 3 6
    4 3 5
    

    输出样例

    impossible
    -3
    

    一、问题解决

    1. \(ax \equiv b \ \ (mod \ m)\)表示\(ax - b\)\(m\)的倍数, 等价为 \(ax = my + b\) , 变形可得 \(ax-my=b\) .

    2. \(y' = -y\),上式变为\(ax + my' = b\),即线性同余方程方程等价为\(ax + my = b\)

    3. 判断是否有解(详见第二部分是否有解)

    4. 运用欧几里得算法求出一组解\(x_0, y_0\), 使得\(ax_0 + my_0 = gcd(a,m)\) ,但题目本身是求\(ax + my = b\),所以两边同时乘以\(\frac{b}{gcd(a,m)}\)即可,即\(x = x_0 \times \frac{b}{gcd(a,b)} \% \ m\)

    二、是否有解

    引入一个定理:裴蜀定理(贝祖定理)

    \(a,b\)不全为零的整数,则存在整数\(x, y\)使得\(ax + by = gcd(a, b)\)

    关于定理的证明: https://oi-wiki.org/math/number-theory/bezouts/

    所以由裴蜀定理可知:

    1. \(gcd(a,m) \ | \ b\)时,方程有解

      整除的解释:'|' 整除号,如a|b (a不为0),若存在整数k,使得b=ka,则称a整除b

    2. 反之,方程无解

    三、扩展欧几里得算法

    用于求解\(ax+by=gcd(a,b)\)的解

    1. \(b = 0\)时,\(ax = a\),此时\(x = 1, y = 0\)

      注意: 当a不为0时,gcd(a, 0) = gcd(0, a) = a

    2. \(b \neq 0\)时,由于\(gcd(a, b) = gcd(b, a\ \% \ b)\)

      代入\(ax + by = gcd(a, b)\)中可联立方程

      \[\begin{aligned} & ax + by = gcd(a,b) \qquad \qquad \qquad①\\ & bx' + (a \ \% \ b)y' = gcd(b, a\ \% \ b)\ \quad② \end{aligned} \]

      因为\(a \% b = a - \lfloor {a/b}\rfloor \times b\),代入整理可得

      \(ay' + b(x' - \lfloor a/b \rfloor \times y') = gcd(b,\ a \% \ b) = gcd(a, b)\)

      所以:

      \[x = y',y = x' - \lfloor a/b \rfloor \times y' \quad ③ \]

    所以可以利用递归算法,求出下一层的\(x' 与 y'\),递归至边界\(b = 0\)时,\(x = 1, y = 0\)

    ,然后再利用公式③回代即可求解

    五、C++代码

    #include <iostream>
    #include <cstdio>
    using namespace std;
    typedef long long LL;
    int n, x, y;
    int exgcd(int a, int b, int &x, int &y){//ax + by = gcd(a, b)
        if(b == 0){
            x = 1, y = 0;
            return a;
        }
        int d = exgcd(b, a % b, x, y);
        int z = x;
        x = y;
        y = z - a / b * y;
        return d;
    }
    
    int main(){
        cin >> n;
        while(n --){
            int a, b, m;
            cin >> a >> b >> m;
            //ax + my = b,传入参数要匹配
            int d = exgcd(a, m, x, y);
            if(b % d) cout << "impossible\n";
            else{
                x = (LL)x * b / d % m;
                cout << x << endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Java+7入门经典 -1 简介
    优化算法动画演示Alec Radford's animations for optimization algorithms
    如何写科技论文How to write a technical paper
    开始学习深度学习和循环神经网络Some starting points for deep learning and RNNs
    用500行Julia代码开始深度学习之旅 Beginning deep learning with 500 lines of Julia
    用10张图来看机器学习Machine learning in 10 pictures
    ICLR 2013 International Conference on Learning Representations深度学习论文papers
    ICLR 2014 International Conference on Learning Representations深度学习论文papers
    卷积神经网络CNN(Convolutional Neural Networks)没有原理只有实现
    卷积神经网络Convolutional Neural Networks
  • 原文地址:https://www.cnblogs.com/PlayfulBlueMoon/p/16397281.html
Copyright © 2020-2023  润新知