对模线性方程 ax = b (mod m),有 ax = k*m + b,其中 k 是整数。
移项后有 ax - km = b,转化到了 EXGCD 的解法。
若有模线性方程组如下:
x=b1(modm1) x = b 1 ( m o d m 1 )
x=b2(modm2) x = b 2 ( m o d m 2 )
x=b3(modm3) x = b 3 ( m o d m 3 )
…………
x=bk(modmk) x = b k ( m o d m k )
需要我们解出一个 x x
方法一:
我们取前两个式子,则有
x=k1∗m1+a1 x = k 1 ∗ m 1 + a 1
x=k2∗m2+a2 x = k 2 ∗ m 2 + a 2
相应变动后有
m1∗k1−m2∗k2=a2−a1 m 1 ∗ k 1 − m 2 ∗ k 2 = a 2 − a 1
其中 m1,m2,a2,a1 m 1 , m 2 , a 2 , a 1 是已知的,由 exgcd 能够得到一组特解 k1,k2 k 1 , k 2 .
k1 k 1 带回第一个式子能得到一个特解 X。
那么其他的解 x=X+k∗lcm(m1,m2) x = X + k ∗ l c m ( m 1 , m 2 ) ,k是自然数。
变形后可以得到
x=X(modlcm(m1,m2)) x = X ( m o d l c m ( m 1 , m 2 ) )
再和 x=b3(modm3) x = b 3 ( m o d m 3 ) 继续上述过程,可以得到所有方程的解。
方法二:
中国剩余定理:
有一次同余方程组如下:
x=b1(modm1) x = b 1 ( m o d m 1 )
x=b2(modm2) x = b 2 ( m o d m 2 )
x=b3(modm3) x = b 3 ( m o d m 3 )
….
x=bk(modmk) x = b k ( m o d m k )
设 m1,m2,m3...mk m 1 , m 2 , m 3 . . . m k 是两两互素的正整数,对于任意的 b1,b2,b3...bk b 1 , b 2 , b 3 . . . b k ,一次同余方程组必定有解,且只有一组解。
令 M=m1∗m2∗m3∗...∗mk M = m 1 ∗ m 2 ∗ m 3 ∗ . . . ∗ m k , Mi=Mmi M i = M m i ,
有 Mi−1 M i − 1 满足 Mi−1∗Mi=1(mod(mi)) M i − 1 ∗ M i = 1 ( m o d ( m i ) ) ,
则同余方程组的解为 x=(∑Mi∗Mi−1∗bi)(modM) x = ( ∑ M i ∗ M i − 1 ∗ b i ) ( m o d M )
方法一代码:
#include
#include
#include
#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
#include
#include
#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;
}