【数论】求逆元的四种方法

逆元的定义 

给定正整数a,p,如果有 ax \equiv 1 \: (mod \; p),且a与p互质,则称x的最小正整数解为a模p的逆元。

一、扩展欧几里得算法

使用条件:基本上通用,不要求p为质数,且效率高,时间复杂度为O(log \: n)

证明过程:ax \equiv 1 \: (mod \; p)有解的条件是gcd(a, p) = 1,即a、p互质,所以根据扩展欧几里得原理,就把问题等价于求解ax + py = 1,就可以使用欧几里得算法了。

void extend_gcd(ll a, ll b, ll &x, ll &y){
    if(b == 0){
        x = 1, y = 0;
        return;
    }
    extend_gcd(b, a % b, x, y);
    ll tmp = x;
    x = y;
    y = tmp - (a / b) * y;
}
ll mod_inverse(ll a, ll mod){
    ll x, y;
    extend_gcd(a, mod, x, y);
    return (x % mod + mod) % mod;
}

二、费马小定理

定理内容:如果p是一个质数,而整数a不是p的倍数,则有a^(p-1)≡1(mod p)。

使用条件:要求p为质数,效率也挺高,但由于扩展欧几里得算法通常情况下更优,因此该方法使用情况较少,时间复杂度为O(log \: n)

证明过程:要证明费马小定理,需要两个引理的辅助:

引理1(剩余系定理2):若a,b,c为任意3个整数,m为正整数,且(m,c) = 1,则当a·c≡b·c(mod m)时,有a≡b(mod m)。

引理2(完全剩余系性质2):若a_{i}(1 \leqslant i \leqslant n)构成模n的完系,k, m \in Z,(m,n) = 1,则k + ma_{i} (1 \leqslant i \leqslant n)也构成模n的完系。

有了这两个引理,我们就可以开始证明了:

对素数p的完全剩余系\left \{ 1, 2, 3, ..., p - 1 \right \},由于(a, p) = 1,根据引理2,\left \{ a, 2a, 3a, ... , (p - 1)a \right \}也是p的一个完全剩余系,由完全剩余系的性质,1 \times 2 \times 3 \times ... \times (p - 1) \equiv a \cdot 2a \cdot 3a \cdot ...\cdot (p - 1)a \; (mod \; p)

(p - 1)! \equiv (p - 1)! \cdot a^{p - 1} \; (mod \; p)

所以a^{p - 1} \equiv 1 \; (mod \; p)得证。

再对其作变形得到a \cdot a^{p - 2} \equiv 1 \; (mod \; p)

令a的逆元为a^{-1},则a^{-1} \equiv a^{p - 2} \; (mod \; p)

ll qmi(ll a, ll b, ll mod){
    ll res = 1;
    while(b){
        if(b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}
ll fermat(ll a, ll mod){
    return qmi(a, mod - 2, mod);
}

三、欧拉定理

定理内容:m,n\in N^{+},且gcd(a, m) = 1,则我们有:a^{\varphi (m)} \equiv 1 \; (mod \; m),其中\varphi (m)称为对模m缩系的元素个数。

使用条件:不要求p为质数,这相当于费马小定理求逆元的扩展,先求出欧拉函数,再求逆元,时间复杂度为O(sqrt(n))

证明过程:取模m的缩系a_1, a_2, ... , a_{\varphi (m)},则aa_1,aa_2,...,aa_{\varphi (m)}也是模m的缩系,故有\prod_{i = 1}^{\varphi (m)} a_i \equiv \prod_{i = 1}^{\varphi (m)} aa_i \equiv a^{\varphi (m)}\prod_{i = 1}^{\varphi (m)} a_i \; (mod \; m) \Rightarrow a^{\varphi (m)} \equiv 1 \; (mod \; m)得证。

再对其作变形得到a \cdot a^{\varphi (m) - 1} \equiv 1 \; (mod \; m)

令a的逆元为a^{-1},则a^{-1} \equiv a^{\varphi (m) - 1} \; (mod \; m)

ll qmi(ll a, ll b, ll mod){
    ll res = 1;
    while(b){
        if(b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}
ll get_phi(ll n){
    ll res = n;
    for(int i = 2; i <= n / i; i++){
        if(n % i == 0){
            res = res / i * (i - 1);
            while(n % i == 0)
                n /= i;
        }
    }
    if(n > 1)
        res = res / n * (n - 1);
    return res;
}
ll mod_inverse(ll a, ll mod){
    if(a % mod != 0)
        return qmi(a, get_phi(mod) - 1, mod);
    else
        return -1;
}

四、递推打表

递推公式:inv[i] = (mod - mod \; / \; i) * inv[mod \; % \; i] \; % \; mod

使用条件:要求p为质数,也是一种常用的求逆元的方法,时间复杂度为O(n)

证明过程:m \; / \; i \; * \; i + m \; % \; i \equiv 0 \; (mod \; m)

             \Rightarrow - m \; / \; i \; * \; i \equiv m \; % \; i \; (mod \; m) 

             \Rightarrow - m \; / \; i \; * \; inv[m \; % \; i] \equiv inv[i] \; (mod \; m)

             \Rightarrow inv[i] \equiv (m - m \; / \; i) \; * \; inv[m \; % \; i] \; (mod \; m)证毕。

ll inv[N];   // 逆元表

void mod_inverse(ll n, ll mod){
    inv[0] = inv[1] = 1;
    for(int i = 2; i <= n; i++)
        inv[i] = (mod - mod / i) * inv[mod % i] % mod;
}

  • 29
    点赞
  • 135
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
扩展欧几里得算法解一元一次不定方程 ax + by = gcd(a,b) 的一种方法,其中 a 和 b 是整数,gcd(a,b) 是它们的最大公约数,x 和 y 是整数解。逆元是指在模运算下,一个数的乘法逆元是指与它相乘后模运算得到 1 的数。在数论中,常常需要一个数在模意义下的逆元,即一个数 k 满足 (k * x) % m = 1,其中 m 是模数。 下面是扩展欧几里得算法逆元的 C 语言实现: ```c #include <stdio.h> // 扩展欧几里得算法 int exgcd(int a, int b, int *x, int *y) { if (b == 0) { *x = 1; *y = 0; return a; } int gcd = exgcd(b, a % b, y, x); *y -= a / b * (*x); return gcd; } // 逆元 int modinv(int a, int m) { int x, y; int gcd = exgcd(a, m, &x, &y); if (gcd != 1) { return -1; // a 和 m 不互质,不存在逆元 } else { return (x % m + m) % m; // 转化为正整数 } } int main() { int a = 3, m = 11; int inv = modinv(a, m); if (inv == -1) { printf("%d 在模 %d 意义下不存在逆元\n", a, m); } else { printf("%d 在模 %d 意义下的逆元是 %d\n", a, m, inv); } return 0; } ``` 这个程序中,exgcd 函数通过递归实现扩展欧几里得算法,返回 a 和 b 的最大公约数,并且出 x 和 y 的值。在 modinv 函数中,我们调用 exgcd 函数出 a 和 m 的最大公约数,并且判断 a 和 m 是否互质,如果不互质则不存在逆元。否则,根据扩展欧几里得算法的结果,出 x 的值作为 a 在模 m 意义下的逆元。注意,由于 x 可能是负数,所以要将其转化为正整数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值