同余方程、中國剩余定理、擴展中國剩余定理、高次同余式
\(1.\) 一次同余方程
\(1.1\) 一次同余方程概述
設方程的一個特解為 \(x_{0}\),那么方程的通解即為
設 \(a^{-1}\) 為 \(a\) 在模 \(m\) 意義下的逆元
那么解的情況可以歸納為
\(1)\) 若 \((a,\ m) = 1\),則方程有一解
\(2)\) 若 \((a,\ m) > 1\)
-
若 \((a,\ m)\mid b\),則方程有 \((a,\ m)\) 個解
\[x\equiv \frac{a}{(a,\ m)}^{-1}\cdot \frac{b}{(a,\ m)}\ (mod\ \frac{m}{(a,\ m)}) + r\cdot \frac{m}{(a,\ m)}\ (mod\ m),\ r = 0,\ 1,\ ...,\ (a,\ m) - 1 \] -
若 \((a,\ m)\nmid b\),則方程無解
\(1.2\) 一次同余方程方程解的情況證明
為了方便敘述,記 \((a,\ m) = d\)
\(1.2.1\) \(d = 1\) 的情況
上述方程存在唯一解 \(x_{0}\),滿足 \(x_{0}\equiv b\cdot a^{-1}\ (mod\ m)\)
證明:
先證明存在性
即證明,若 \(d = 1\),上述方程存在解
考慮方程
由於 \(d = 1\) ,所以
所以 \(s\) 即為方程
的一個特解
事實上, \(s\equiv\ a^{-1}\ (mod\ m)\)
將其乘以 \(b\),得到方程
的解為
至此,存在性證畢!
下證唯一性
設方程
有兩個特解 \(x_{1},\ x_{2}\)
則
由於 \((a,\ m) = 1\) ,所以 \(x_{1}\equiv x_{2}\ (mod\ m)\)
唯一性證畢!
\(1.2.2\) \(d > 1\) 的情況
若 \(d\mid b\),方程有 \(d\) 個解
若 \(d\nmid b\),方程無解
先證明必要性
即證明,若方程有解,則 \(d\mid b\)
由於 \(d = (a,\ m)\),所以 \(d\mid a,\ d\mid m\),所以 \(d\mid ax\)
又 \(ax\equiv b\ (mod\ m)\),所以 \(m\mid ax - b\)
所以 \(d\mid ax - b\)
所以 \(d\mid b\)
必要性證畢!
下證明充分性
考慮方程
由於 \((\frac{a}{d},\ \frac{m}{d}) = 1\)
所以上述方程存在解
通解可以寫為
帶一點技巧性地
設
所以通解可以變為
於是
由於 \(r\) 有 \(d\) 個值,所以方程的解有 \(d\) 個
充分性證畢!
\(1.3\) 一次同余方程 \(code\)
多組數據按順序讀入 \(a,\ b,\ m\),多個解按照從小到大的順序輸出
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
#define arrayDebug(a, l, r) for(int i = l; i <= r; ++i) printf("%d%c", a[i], " \n"[i == r])
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int DX[] = {0, -1, 0, 1, 0, -1, -1, 1, 1};
const int DY[] = {0, 0, 1, 0, -1, -1, 1, 1, -1};
const int MOD = 1e9 + 7;
const int N = 1e6 + 7;
const double PI = acos(-1);
const double EPS = 1e-6;
using namespace std;
inline int read()
{
char c = getchar();
int ans = 0, f = 1;
while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
while(isdigit(c)) {ans = ans * 10 + c - '0'; c = getchar();}
return ans * f;
}
int exgcd(int a, int b, int &x, int &y)
{
if(!b) {x = 1, y = 0; return a;}
int r = exgcd(b, a % b, y, x);//y的值被修改為x',x的值被修改為y'
y -= a / b * x;
return r;
}
int cnt, ans[N] = {0};
int main()
{
int a, b, m;
while(cin >> a >> b >> m){
cnt = 0, memset(ans, 0, sizeof(ans));
int x, y;
int d = exgcd(a, m, x, y);
if(b % d) puts("No Answer.");
else {
int r = exgcd(a / d, m / d, x, y);
while(x < 0) x += m / d;
for(int i = 0; i < d; ++i)
ans[++cnt] = (b / d * x + i * m / d) % m;
sort(ans + 1, ans + 1 + cnt);
for(int i = 1; i <= cnt; ++i)
printf("%d%c", ans[i], " \n"[i == cnt]);
}
}
return 0;
}
\(2.\) 中國剩余定理
給定線性同余方程組
保證 \(m_{1},\ m_{2},\ ...\ m_{n}\) 兩兩互質
\(2.1\) 中國剩余定理 \(CRT\) 概述
設
以及
則上述同余方程組的通解為
\(2.2\ CRT\) 解的求解與證明
考慮對於每一個線性同余方程
求出對應的一個特解 \(x_{i}\) ,且這個 \(x_{i}\) 要滿足
把 \(n\) 個這樣的 \(x_{i}\) 求和,就可以得到方程組的一個特解 \(x\)
設
以及
分析 \(x_{i}\) ,其必然是 \(M_{i}\) 的整數倍,且滿足
設
有
只要能夠解出 \(y\) ,便能得到 \(x\) 的特解;反之,線性同余方程組無解
因為 \((M_{i},\ m_{i}) = 1\)
所以由擴歐算法得到
所以
將 \(n\) 個 \(x_{i}\) 求和得到 \(x\) 的一個特解
為了滿足題意, \(x\) 的通解為
特殊的, \(x\) 的最小非負解為
\(2.3\ CRT\ code\)
int n, a[N], p[N];
LL M = 1;
int exgcd(int a, int b, int &x, int &y)
{
if(!b) {x = 1, y = 0; return a;}
int r = exgcd(b, a % b, y, x);//y的值被修改為x',x的值被修改為y'
y -= (a / b) * x;
return r;
}
int inv(int a, int p)
{
int x = 0, y = 0;
int gcd = exgcd(a, p, x, y);
while(x < 0) x += p;
return x;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
for(int i = 1; i <= n; ++i)
scanf("%d", &p[i]);
for(int i = 1; i <= n; ++i)
M *= p[i];
int x = 0;
for(int i = 1; i <= n; ++i){
x += a[i] * inv(M / p[i], p[i]) * M / p[i], x %= M;
}
printf("%d\n", x);
return 0;
}
\(3.\) 擴展中國剩余定理
給定線性同余方程組
\(m_{1},\ m_{2},\ ...\ m_{n}\) 不一定兩兩互質
\(3.1\) 擴展中國剩余定理概述
設
則上述方程組通解為
其中 \(x_{0}\) 是同余方程組的一個特解,通過 \(n - 1\) 次擴歐算法計算得出
\(3.2\ EXCRT\) 的解
考慮已經解出前 \(k-1\) 個方程的解 \(x_{1}\)
習慣的,我們設
但為了防止溢出,設
那么前 \(k-1\) 個方程的通解為
設 \(x_{2} = x_{1} + t\cdot m,\ t\in \mathbb{Z}\)
將 \(x_{2}\) 代入第 \(k\) 個式子
即
若
則線性同余方程組無解
若
由擴歐算法解出 \(t\),得到特解 \(x_{2}\)
那么新的通解為
如此循環
\(excrt\) 的本質便是合並方程
對於 \(n\) 個方程的線性同余方程組,本質上是作 \(n-1\) 次擴展歐幾里得算法
\(3.3\) \(EXCRT\ code\)
處理到第 \(k\) 個方程時,具體求 \(x_{2}\) 的過程如下
因為
其中
所以即在方程中求 \(t\)
先用擴歐求方程
的特解 \(t_{0}\),然后自乘系數
進而得到通解
為了防止溢出,將 \(t\) 取模數 \(\frac{m_{k}}{(m,\ m_{k})}\) 至最小非負數
於是得到
int n;
LL a[N], p[N];
LL qmul(LL a, LL b, LL mod)
{
LL res = 0;
while(b > 0) {
if(b & 1) res += a, res %= mod;
a += a, a %= mod;
b >>= 1;
}
return res;
}
LL exgcd(LL a, LL b, LL &x, LL &y)
{
if(!b) {x = 1, y = 0; return a;}
LL r = exgcd(b, a % b, y, x);
y -= a / b * x;
return r;
}
LL excrt(LL n, LL *a, LL *p)
{
LL M = p[1];//維護LCM
LL x = a[1];//維護解
for(int i = 2; i <= n; ++i){
LL xx = 0, yy = 0;
LL gcd = exgcd(M, p[i], xx, yy);
LL c = (a[i] - x % p[i] + p[i]) % p[i];
LL ag = p[i] / gcd;
if(c % gcd) return -1;
c /= gcd;
//若數據較大,使用快速乘防止溢出
//LL t = qmul(xx, c, ag);
LL t = (xx * c) % ag;
x += t * M;//得到新的特解
M *= ag;//更新LCM
x = (x % M + M) % M;//將x更新到最小
}
return x;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%lld %lld", &p[i], &a[i]);
LL ans = excrt(n, a, p);
if(ans == -1) puts("-1");
else printf("%lld\n", ans);
return 0;
}
\(4.\) 求解高次同余式
設
求解
\(4.1\) 解高次同余式的等價以及解的數量
求高次同余式
等價於
求高次同余式組
證明思路如下
設方程 \(f(x)\equiv 0\ (mod\ m_{i})\) 為 \(T_{i}\)
設方程 \(f(x)\equiv 0\ (mod\ m)\) 為 \(T\)
只要證明,方程組 \(T_{i}\) 的所有解都是方程 \(T\) 的解,以及方程 \(T\) 的所有解都是方程組 \(T_{i}\) 的解即可
先證明,方程組 \(T_{i}\) 的所有解都是方程 \(T\) 的解
若對於任意 \(i\),都有 \(f(x_{0})\equiv 0\ (mod\ m_{i})\)
那么說明 \(f(x_{0})\) 是 \(m_{1},\ m_{2},\ ...,\ m_{n}\) 的公倍數
而 \(m = m_{1}m_{2}...m_{n} = [m_{1}m_{2}...m_{n}]\)
所以 \(f(x_{0})\equiv 0\ (mod\ m)\)
設方程 \(T_{i}\) 的解為 \(x\equiv b_{i}\ (mod\ m_{i})\)
則
由中國剩余定理,方程組 \(T_{i}\) 的解為
有
所以
即方程組 \(T_{i}\) 的所有解都是方程 \(T\) 的解
下證明,方程 \(T\) 的所有解都是方程組 \(T_{i}\) 的解
若 \(f(x)\equiv 0\ (mod\ m)\)
則 \(f(x)\equiv 0\ (mod\ m_{i})\)
這是因為 \(m_{i}\mid m\mid f(x)\)
所以方程 \(T\) 的所有解都是方程組 \(T_{i}\) 的解
\(Q.E.D.\)
設 \(T_{i}\) 解的數量為 \(t_{i}\),\(T\) 解的數量為 \(t\)
由乘法原理知道
\(4.2\) 求解模為素數冪的高次同余式
\(4.2.1\) 概述及其意義
對於整系數高次多項式
考慮同余方程
若方程有一個解
且
則上述同余式有解
其中有遞推關系如下
由於任何數都可以被分解成素數冪的積的形式,結合高次同余式解的等價,所以解任何模數的高次同余方程,都可以化為求解模為素數冪的情況
\(4.2.2\) 解的證明
對 \(\alpha\geq 2\) 做數學歸納法證明
\(1)\) 當 \(\alpha = 2\) 時
同余式有解
設
下解
考慮多項式
由小學二年級學會的二項式定理
即
得到
即
其中 \(A\in \mathbb{Z}\)
所以
即解
由於
所以
這一步用到的定理如下:
若 \(d\) 是 \(a,\ b,\ m\) 的公因數
則 \(a\equiv b\ (mod\ m)\Leftrightarrow \frac{a}{d}\equiv \frac{b}{d}\ (mod\ \frac{m}{d})\)
簡易證明如下:
若 \(a\equiv b\ (mod\ m)\),則 \(m\mid (a - b)\)
若 \(d\mid a,\ b,\ m\)
則 \(\frac{m}{d}\mid\ \frac{a}{d} - \frac{b}{d}\),即 \(\frac{a}{d}\equiv \frac{b}{d}\ (mod\ \frac{m}{d})\)
結合 \((f'(x_{1},\ p)) = 1\),兩邊同時乘以 \(f'(x_{1})\) 在模 \(p\) 意義下的逆元
即
求出了 \(t_{1}\),對應的 \(x_{2} = x_{1} + t_{1}\cdot p\) 便滿足
得證!
\(2)\) 假設 \(\alpha = k\) 時,有 \(x_{k}\) 滿足 \(f(x_{k})\equiv 0\ (mod\ p^{k})\)
且有
則 \(\alpha = k + 1\) 時,求解
設 \(x_{k + 1} = x_{k} + t_{k}\cdot p^{k}\),代入上式得到
由於 \(2k\geq k + 1\)
所以
由歸納假設, \(f(x_{k})\equiv 0\ (mod\ p^{k})\)
所以
由於
所以
結合 \((f'(x_{1}),\ p) = 1\),知道 \((f'(x_{k}),\ p) = 1\)
考慮兩邊同時乘以 \(f'(x_{k})\) 在模 \(p\) 意義下的逆元
所以
即
求出了 \(t_{k}\),對應的 \(x_{k + 1} = x_{k} + t_{k}\cdot p^{k}\) 便滿足
所以 \(\alpha = k + 1\) 時也成立
綜上所述,命題得證!