數論—模運算的逆元


目錄

有關模運算

定義

運算規則

逆元

定義

使用方法

求逆元的方法

枚舉法

拓展歐幾里得(Extend - Eculid)

費馬小定理(Fermat's little theorem)

注意


有關模運算

  • 在信息學競賽中,當答案過於龐大的時候,我們經常會使用到模運算(Modulo Operation)來縮小答案的范圍,以便輸出計算得出的答案。
  • 定義

給定一個正整數 p,任意一個整數 n,那么一定存在等式:

n = k * p + r;

其中k、r 是整數,且0 ≤ r < p,則稱 k 為 n 除以 p 的商,r 為 n 除以 p 的余數。

對於正整數 p 和正整數 a、b,定義如下運算:

  • 取模運算 : a % p (或 a mod p),表示 a 除以 p 的余數。
  • 模 p 加法:(a + b) % p,其結果是 a + b 算術和除以 p 的余數。
  • 模 p 減法:(a - b) % p,其結果是 a - b 算術差除以 p 的余數。
  • 模 p 乘法:(a * b) % p,其結果是 a * b 算數積除以 p 的余數。
  • 同余式:正整數 a、b 對 p 取模,他們的余數相同,記做 a ≡ b (mod p)。

說明:

n % p 得到結果的正負由被除數 n 決定,與 p 無關。

例如:7 % 4 = 3, -7 % 4 = -3, -7 % -4 = -3.

  • 運算規則

    • 模運算與基本四則運算有些相似,但是除法除外。其規則如下:
      • (a + b) % p = (a % p + b % p) % p
      • (a - b) % p = (a % p - b % p) % p
      • (a * b) % p = (a % p * b % p) % p
      • a ^ b % p = ((a % p) ^ b) % p
      • 結合律
        • ((a + b) % p + c) = (a + (b + c) % p) % p
        • ((a * b) % p * c) = (a * (b * c) % p) % p
      • 交換律
        • (a + b) % p = (b + a) % p
        • (a * b) % p = (b * a) % p
      • 分配律
        • (a + b) % p = (a % p + b % p) % p
        • ((a + b) % p * c) % p = ((a * c) % p + (b * c) % p
    • 重要定理
      • 若 a ≡ b (mod p),則對於任意的 c,都有(a + c) ≡ (b + c) (mod p)
      • 若 a ≡ b (mod p),則對於任意的 c,都有(a * c) ≡ (b * c) (mod p)
      • 若 a ≡ b (mod p),c ≡ d (mod p),則
        • (a + c) ≡ (b + d) (mod p)
        • (a - c) ≡ (b - d) (mod p)
        • (a * c) ≡ (b * d) (mod p)
        • (a / c) ≡ (b / d) (mod p)

逆元

前文已經說過,模運算的除法運算規則與普通四則運算不同,那么當(a / b)的中間運算結果過大怎么辦?

使用逆元可以很好地解決這個問題。

定義

逆元是指在數學領域群G中任意一個元 a,都在G中有唯一的逆元a',具有性質 a · a' = a' · a = e ( · 為該群中定義的運算)。其中,e為該群的單位元。

逆元其實是加法中的相反數以及乘法中的倒數的拓展思想。

在模運算中,單位元便是1。

a mod p的逆元便是可以使 a * a' mod p = 1 的最小a'。

使用方法

因為 b' 為 b 的逆元,b * b' mod p = 1;

所以 (a / b) mod p = (a * b') mod p ,但要求a | b;

這樣我們便可以應用 (a * b) % p = (a % p * b % p) % p 這一條性質縮小中間運算結果了。

求逆元的方法

  1. 枚舉法;
  2. 利用拓展歐幾里得算法求解同余方程;
  3. 費馬小定理。

枚舉法

枚舉1到p - 1的整數bi,若b * bi % p = 1,則bi即為b mod p的乘法逆元。

為什么只枚舉到p - 1呢?

1. 如果枚舉到 p,那么顯然 b * p % p = 0;;

2. 如果枚舉到 p + k ( 0 < k < p),那么有 b * (p + k) % p = b * p % p + b * k % p = b * k % p,這樣就返回了枚舉1到p - 1的情況;

3. 如果枚舉到 p + k ( k > p),同第二種情況。

拓展歐幾里得(Extend - Eculid)

求最小整數x、y,使 x * a + y * b = gcd(a , b);

類似這樣的問題便可以使用拓展歐幾里得來求解。

由歐幾里得定理可知gcd(a , b) = gcd(b , a % b) (假設 a > b),

所以有x' * b + y' * (a % b) = gcd(a , b),假設已經求得 x' 和 y',那么有 :

x' * b + y' * ( a % b) = gcd(a , b) and a % b = a - [a / b] * b

∴ x' * b + y' * ( a - [a / b] * b) = gcd(a , b)

∴ y' * a + (x' - y' * [a / b]) * b = gcd(a , b)

如此這個問題便可以遞歸的求解了。

(顯然如果b = 0的話,那么x = 1,y = 0)

那么求解 b' 使得 b * b‘ mod p = 1 這個問題便可以轉化為:

求最小整數 b'、k,使得 b' * b + k * p = 1;

代碼實現:

#include<iostream>
using namespace std;
void ext_gcd(int a,int b,int &d,int &x,int &y) {
    if(b == 0) {
	d = a; x = 1; y = 0;
	return;
    }
    ext_gcd(b,a % b,d,y,x);
    y -= a / b * x;
    return;
}
int main() {
    int x,y,d;
    int a,b; 
    while(1) {
	cin >> a >> b;
	ext_gcd(a,b,d,x,y);
	if(d != 1) cout << "There is no ans for this input." << endl;
	else cout << "The ans for this input : " << (x + b) % b << endl;
    }
    return 0;
} 

費馬小定理(Fermat's little theorem)

假如 p 是質數,那么 a ^ (p-1) ≡ 1 (mod p) 。

推論: b ^ (p - 2) % p 即為 b mod p 的乘法逆元。

注意

需要b、p互質才可以使用逆元法,如果b、p不互質的話只能用(a / b) % p = (a % (b * p)) / b 來嘗試解決問題了。

但是在信息競賽中一般給出的模數均為質數,例如10 ^ 9 + 7 。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM