我是靠谱客的博主 忧伤金鱼,最近开发中收集的这篇文章主要介绍逆元概念及其求解方法逆元,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

逆元

引出

存在取模运算公式:

(a + b) % c = (a % c + b % c) % c

(a * b) % c = (a % c * b % c) % c

(a - b) % c = (a % c - b % c + c) % c

但是不存在取模运算公式:

(a / b) % c = (a % c / b % c) % c

这时候逆元就出现了,逆元就是在mod下,不能直接除以一个数,而是要乘以它的逆元。

我们令inv(b)表示b的逆元,即inv(b) = b ^ -1

那么对于公式 (a / b) % c = (a % c / b % c) % c 我们可以写成乘法取模运算的形式,

可以转化成 (a * inv(b)) % c = (a % c * inv(b) % c) % c, 这样不就合法了。

逆元概念:

概念:

你元素是指一个可以取消另一给定元素运算的元素,在数学里,逆元素广义化了加法中的加法逆元和乘法中的倒数。

加法逆元:

对于一个数n, n和其加法逆元(或称相反数)之和是加法单位(即数字0)。

Eg:

8的加法逆元是-8

-0.5的加法逆元是0.5

乘法逆元:

对于任意的整数a,满足b|a(a能够被b整除),则存在一个整数x,使得 a / b ≡ a * x (mod p) 称 x 为 b 的模p 乘法逆元, x记为b ^ -1 (mod p)。

我们对于该同余等式 a / b ≡ a * x (mod p)进行化简:

两边同成b: a ≡ a * b * x (mod p)

两边同时除以a: 1 ≡ b * x (mod p)

化简结果为: b * x ≡ 1(mod p)

为了方便记我们就写成:ax ≡ 1 (mod p)

乘法逆元的充分必要条件以及求解方法:

我们在上述已经介绍了乘法逆元,即它的形式是: ax ≡ 1 (mod p)

那么什么时候这个同余等式是有解的呢?(即它的充分必要条件)

充分必要条件: a存在逆元的充分必要的条件是a与模数p互质。(互质数即两个或多个整数的公因数只有1的非零自然数)

求解方法:

对于p是否为质数,我们可以分成两种求乘法逆元的方法。

1)当p为质数,可以用快速幂求逆元(费马小定理)

由费马小定理可知,当p为质数时

a^(p - 1)≡ 1 (mod p)

拆出一个a来可得:a * a * (p - 2) ≡ 1 (mod p)

故当p为质数时,a的乘法逆元 x = a ^ (p - 2)

当然可能数p - 2很大,我们用快速幂来求解即可。

特例:

对于a是p的倍数的情况,其公约数时p,a和p肯定是不互质的,所以无解,即ax % p = 0

但是当a = 2, p = 2, a ^ (p - 2)= 2 ^(2 - 2) ≡ 1 mod(p)

因此对于a = 2 , p = 2 的情况需要特别判断一下(一般通过a % p == 0的方法判断掉)。

代码:

递归版(重复调用函数)

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int INF = 1e9;
const int N = 1e5 + 5;
int n;
int a,b,p;
ll quick_mi(ll a,int b,int p){
    if(b==0)return 1;//指数可能会取到0
    if(b==1)return a%p;
    else if(b%2==1)return quick_mi((a*a)%p,b/2,p)*a%p;
    else if(b%2==0)return quick_mi((a*a)%p,b/2,p)%p;
}
int main()
{
    cin>>n;
    while(n--){
        cin>>a>>p;
        if(a%p!=0)cout<<quick_mi(a,p-2,p)<<endl;
        else cout<<"impossible"<<endl;
    }
    return 0;
}


迭代版(重复使用一个结构)

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int INF = 1e9;
const int N = 1e5 + 5;
int n,a,p;
ll quick_mi(int a,int b,int p){
    ll res=1;
    while(b){
        if(b&1)res=res*a%p;
        a=a*(ll)a%p;
        b>>=1;
    }
    return res;
}
int main()
{
    cin>>n;
    while(n--){
        cin>>a>>p;
        if(a%p!=0)cout<<quick_mi(a,p-2,p)<<endl;
        else cout<<"impossible"<<endl;
    }
    return 0;
}

2)当p不为质数,可以用扩展欧几里得算法求逆元

由充分必要条件知,a有逆元的充要条件是a 与 p 互质,即 gcd(a, p) = 1

假设a的逆元为x,那么有a * x ≡ 1 (mod p)

等价: ax + py = 1

通过扩展欧几里得算法求解exgcd(a, p, x, y)即可。

最后

以上就是忧伤金鱼为你收集整理的逆元概念及其求解方法逆元的全部内容,希望文章能够帮你解决逆元概念及其求解方法逆元所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部