这部分内容介绍了同余方程,类Euclid算法等内容
线性同余方程
对于线性同于方程 ax≡c(modb)
定理1,方程 ax+by=c 等价于方程 ax≡c(modb)
有整数解的充要条件是 gcd(a,b)∣c
algorithm
用扩展Euclid算法求解出一组 x0,y0,满足 ax0+by0=gcd(a,b)
两边同时除以 gcd(a,b),再 ×c
acx0/gcd(a,b)+bcy0/gcd(a,b)=c
gcd(a,b)cx0,gcd(a,b)cy0
定理2, 若 gcd(a,b)=1,并且 x0,y0 是方程
ax+by=c 的一组解,那么方程的任意解可以表示为
∀t∈Z,x=x0+bt,y=y0−at
因为此时 t 为任意整数都可以成立,这个时候我们可以求出方程的所有解
但实际问题中,我们只需要求解一个最小整数解就可以了
实际上,根据定理1,我们可以把一般解式表示为
x=gcd(a,b)cx0+k⋅gcd(a,b)by=gcd(a,b)cy0−k⋅gcd(a,b)a∀k∈Z
注意到 k 可以取任意整数
方程的通解实际上是
modgcd(a,b)b≡x≡gcd(a,b)cx0
就是一类同余数,modgcd(a,b)b余数是
gcd(a,b)cx0
最小的数,一般取 k=1,此时对一个特解 x
t=gcd(a,b)b,x=(xmodt+t)modt
LOJ2605 同余方程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| ll a, b;
ll exgcd(ll a, ll b, ll &x, ll &y) { if (b == 0) { x = 1, y = 0; return a; }
ll d = exgcd(b, a%b, x, y); ll z = x; x = y; y = z - (a/b)*y; return d; }
int main() { freopen("input.txt", "r", stdin); cin >> a >> b;
ll x, y; exgcd(a, b, x, y); ll res = (x % b + b) % b; cout << res << endl; }
|
扩展Euclid算法求解线性同余方程
ax≡c(modb)
也就是 ax+by=c 方程的解,要求求出一个最小的 x
- algorithm
- d=exgcd(a,b,x,y)⇒get x
计算出一个特解 x
- cmodd=0,没有解
else k=c/d
x←(x⋅k)modb,y←(y⋅k)modb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| inline ll exgcd(ll a, ll b, ll &x, ll &y) { if (!b) { x = 1, y = 0; return a; } ll d = exgcd(b, a%b, x, y); ll z = x; x = y; y = z - (a/b) * y; return d; }
bool liEu(ll a, ll b, ll c, ll &x, ll &y) { ll d = exgcd(a, b, x, y); if (c % d) return 0;
int k = c/d; x = (x * k) % b; y = (y * k) % b; return 1; }
|
中国剩余定理
mi 不再两两互质情况下的中国剩余定理
POJ2891
假设解完前 k 个线性同余方程之后得到的特解是 x
m=lcm(m1,m2,⋯,mk)
通解可以表示成 x+km(k∈Z)
最小非负整数解为 xmodm
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| typedef unsigned long long ull; int n;
inline ll exgcd(ll a, ll b, ll &x, ll &y) { if (!b) { x = 1, y = 0; return a; } ll d = exgcd(b, a%b, x, y); ll z = x; x = y; y = z - (a/b) * y; return d; }
void solve(int n) { ll a, r; cin >> a >> r; ll ans = r, lcm = a; bool fl = true;
n--; while (n--) { cin >> a >> r;
// exgcd r = (r - ans % a + a) % a; ll x, y, x2; ll d = exgcd(lcm, a, x, y); if (r % d) fl = false; else x2 = x * (r/d) % a;
ans += x2 * lcm; // update lcm, and get min ans lcm = (lcm / d) * a; ans = (ans % lcm + lcm) % lcm; }
if (fl) cout << ans << endl; else cout << "-1" << endl; }
void init() { // }
int main() { freopen("input.txt", "r", stdin); while (cin >> n) { init();
solve(n); } }
|
CRT算法图解
高次同余方程