模线性方程组、中国剩余定理

本文介绍了解模线性方程及方程组的方法,包括通过扩展欧几里得算法解单个方程和利用中国剩余定理解方程组。提供了两种解法的具体步骤及对应的C++实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对模线性方程 ax = b (mod m),有 ax = k*m + b,其中 k 是整数。
移项后有 ax - km = b,转化到了 EXGCD 的解法。


若有模线性方程组如下:
x=b1(modm1)x=b1(modm1)
x=b2(modm2)x=b2(modm2)
x=b3(modm3)x=b3(modm3)
…………
x=bk(modmk)x=bk(modmk)
需要我们解出一个 xx


方法一:

我们取前两个式子,则有
x=k1m1+a1
x=k2m2+a2x=k2∗m2+a2
相应变动后有
m1k1m2k2=a2a1m1∗k1−m2∗k2=a2−a1
其中 m1m2a2a1m1,m2,a2,a1 是已知的,由 exgcd 能够得到一组特解 k1k2k1,k2.
k1k1 带回第一个式子能得到一个特解 X。
那么其他的解 x=X+klcm(m1,m2)x=X+k∗lcm(m1,m2),k是自然数。
变形后可以得到
x=X(modlcm(m1,m2))x=X(modlcm(m1,m2))
再和 x=b3(modm3)x=b3(modm3) 继续上述过程,可以得到所有方程的解。


方法二:

中国剩余定理:

有一次同余方程组如下:
x=b1(modm1)x=b1(modm1)
x=b2(modm2)x=b2(modm2)
x=b3(modm3)x=b3(modm3)
….
x=bk(modmk)x=bk(modmk)

m1,m2,m3...mkm1,m2,m3...mk两两互素的正整数,对于任意的 b1,b2,b3...bkb1,b2,b3...bk,一次同余方程组必定有解,且只有一组解。

M=m1m2m3...mkM=m1∗m2∗m3∗...∗mkMi=MmiMi=Mmi
Mi1Mi−1 满足 Mi1Mi=1(mod(mi))Mi−1∗Mi=1(mod(mi))
则同余方程组的解为 x=(MiMi1bi)(modM)x=(∑Mi∗Mi−1∗bi)(modM)


方法一代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#define ll long long
using namespace std;

ll mr[105];
ll ar[105];

ll exgcd (ll a, ll b, ll &x, ll &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    ll r = exgcd(b, a%b, x, y);
    ll t = x;
    x = y;
    y = t - a/b*y;
    return r;
}

ll solve (int n) {
    ll M = mr[1], A = ar[1], x, y;
    for (int i = 2; i <= n; i++) {
        ll d = exgcd(M, mr[i], x, y);
        if (abs(A - ar[i]) % d != 0) {
            return -1;
        }
        x = (A - ar[i]) / d * x;
        ll tmp = ar[i] / d;
        x = x % tmp;
        A = x*M + A;
        M = M*ar[i]/d;
        A = A % M;
        if (A < 0) {
            A += M;
        }
    }
    if (A == 0) {
        return M;
    }
    else {
        return (A%M+M)%M;
    }
}

方法二代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#define ll long long
using namespace std;

ll mr[105];     //模
ll ar[105];     //余数

ll exgcd (ll a, ll b, ll &x, ll &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    ll r = exgcd(b, a%b, x, y);
    ll t = x;
    x = y;
    y = t - a/b*y;
    return r;
}

ll solve (int n) {
    ll ans = 0, M = 1;
    for (int i = 1; i < n; i++) {
        M *= ar[i];
    }
    for (int i = 1; i <= n; i++) {
        ll tmp = M / mr[i];
        ll x, y;
        exgcd(tmp, mr[i], x, y);
        ans = (ans + tmp*x*ar[i]) % M;
    }
    return (ans%M+M)%M;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值