逆元
逆元概念
引入逆元
数论中的 (a / b)% p 运算很不方便,而且对p同余不满足同除性,因此引入逆元将整除运算转换为整数乘法运算,会更有助于计算。
定义
若 a * x ≡ 1 (mod) b, a, b 互质,则称 x 为 a 的逆元,标记为 a -1。
逆元也可认为是数论意义上的倒数。
a 模 b 意义上的逆元不唯一,一般方便计算,取(0,b - 1]范围的逆元。
用法
逆元可以用来计算(t / a)mod b 时,转化为 t * a-1 mod b
两表达式同余证明:
(t / a)mod b == ((t / a)mod b)(1 mod b) == ((t / a)mod b)(a * a-1 mod b) == t * a-1 mod b
相关知识介绍
- 欧拉函数
对于正整数n,欧拉函数是小于等于n的数中与n互质的数的数目。
欧拉函数又称为 φ 函数,例如φ (8) = 4, 因为1,3,5,7均和8互质。
如果n为素数,则: φ (n)= n - 1 。
φ (1) = 1
一般情况: φ ( N ) = N ∗ ( 1 − 1/ p 1 ) ∗ ( 1 − 1/ p 2 ) ∗ . . . ∗ ( 1−1 /p k )
p1,p2,…, pk 是N的所有质因数。
- 欧拉定理
定理:若正整数 a, m互质,则有 a ^φ ( m ) ≡ 1 ( m o d m )
- 费马小定理
费马定理是欧拉定理的特例,当模数m为素数时,欧拉定理可以简化为:a ^( m - 1 ) ≡ 1 ( m o d m )
- 扩展欧几里得算法
扩展欧几里得算法用于在已知(a,b)时,求解一组(x,y),使得x * a + y * b =GCD(a,b)。
// 求x, y,使得ax + by = gcd(a, b)
int exgcd(int a, int b, int &x, int &y)
{
//如gcd是1,则x 存放a的模b意义上的逆元
if (!b)
{
x = 1; y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= (a/b) * x;
return d;// d is gcd
}
逆元解法
费马小定理求解
费马小定理只适用于模数是质数的情况。
由 a ^( m - 1 ) ≡ 1 ( m o d m ) 推出 a * a ^( m - 2 ) ≡ 1 ( m o d m )
则a ^( m - 2 )是a模m意义上的逆元。
欧拉定理求解
欧拉定理对于模数是合数和质数的情况都能求解逆元。
由a ^φ ( m ) ≡ 1 ( m o d m )推出 a * a ^(φ ( m )-1) ≡ 1 ( m o d m )
则a ^(φ ( m )-1)是a模m意义上的逆元。
(a ^(φ ( m )-1))% m 是最小的正整数逆元。
//欧拉函数
int phi(int p)
{
int res = p;
for(int i = 2; i <= p / i; i ++)
if(p % i == 0)
{
while(p % i == 0) p /= i;//update p
res = res / i * (i -