• 模线性方程&&中国剩余定理及拓展


    一、求解模线性方程

    由ax=b(mod n)

    可知ax = ny + b

    就相当于ax + ny = b

    由扩展欧几里得算法可知有解条件为gcd(a, n)整除d

    可以直接套用扩展欧几里得算法

    最终由d个不同解时在模n下有d个不同的数字

    二、中国剩余定理

    证明可看:https://www.cnblogs.com/MashiroSky/p/5918158.html

    ll extgcd(ll a, ll b, ll& x, ll& y)
    //求解ax+by=gcd(a, b)
    //返回值为gcd(a, b)
    {
        ll d = a;
        if(b)
        {
            d = extgcd(b, a % b, y, x);
            y -= (a / b) * x;
        }
        else x = 1, y = 0;
        return d;
    }
    ll solve(ll a[], ll m[], int n)//a数组是余数,m数组是两两互质的数字
    {
        ll M = 1, ans = 0;
        for(int i = 0; i < n; i++)M *= m[i];
        //cout<<M<<endl;
        for(int i = 0; i < n; i++)
        {
            ll mi = M / m[i], x, y;
            extgcd(mi, m[i], x, y);
            //求出mi模上m[i]的逆元x  mi * x + m[i] * y = gcd(mi, m[i]) = 1(两两互质)
            ans = ans + ((a[i] % M) * (mi % M) % M) * (x % M) % M;
            ans = (ans % M + M) % M;
        }
        return ans;
    }

    三、中国剩余定理扩展---求解一般的模线性方程组

      普通的中国剩余定理要求所有的互素,那么如果不互素呢,怎么求解同余方程组?

      这种情况就采用两两合并的思想,假设要合并如下两个方程:

      那么得到:

      我们需要求出一个最小的xx使它满足:

    在代码中,每次求出m0 * x + m[i] * y = a[i] - a0的解x的时候,对x模上m[i],这是为了保证x绝对值较小,防止之后的乘法溢出,

    x的通解就是x + k * m[i] / gcd(m0, m[i]),此处模上m[i] / gcd(m0, m[i])更好

     1 ll extgcd(ll a, ll b, ll& x, ll& y)
     2 //求解ax+by=gcd(a, b)
     3 //返回值为gcd(a, b)
     4 {
     5     ll d = a;
     6     if(b)
     7     {
     8         d = extgcd(b, a % b, y, x);
     9         y -= (a / b) * x;
    10     }
    11     else x = 1, y = 0;
    12     return d;
    13 }
    14 ll solve(ll a[], ll m[], int n)//a数组是余数,m数组是除数
    15 {
    16     ll m0 = m[0], a0 = a[0];
    17     for(int i = 1; i < n; i++)
    18     {
    19         ll x, y;
    20         ll g = extgcd(m0, m[i], x, y);//求出m0 * x + m[i] * y = gcd(x, y)
    21         if((a[i] - a0) % g)return -1;
    22         x = x * (a[i] - a0) / g % m[i];  
    23         //求出m0 * x + m[i] * y = a[i] - a0的解x
    24         //此处模上m[i]是为了取绝对值最小的一个x,因为x的通解就是x+k*m[i]
    25         ll K = x * m0 + a0;     //代回原式,求出最大的K
    26         m0 = m0 / g * m[i];     //m0更新为m0和m[i]的lcm
    27         a0 = K;                 //a0更新为K
    28         a0 = ((a0 % m0) + m0) % m0;
    29     }
    30     return a0;
    31 }
  • 相关阅读:
    java23种设计模式-结构型模式-适配器模式
    java23种设计模式-创建者模式-抽象工厂模式
    java23种设计模式-创建者模式-工厂模式
    从jvm运行数据区分析字符串是否相同
    Linux常见安全策略
    MySQL 报错案例分析
    Linux系统网络监控工具
    海量运维架构
    Linux运维面试技巧
    DBA机遇于风险并存
  • 原文地址:https://www.cnblogs.com/fzl194/p/9017049.html
Copyright © 2020-2023  润新知