逆元(费马小定理、扩展欧几里得、逆元线性打表)

news/2024/11/29 7:57:33/

逆元

  • 逆元应用与证明
    • 费马小定理方法
    • 扩展欧几里得求逆元
      • 这里给出扩展欧几里得算法的模板代码:
    • 打表求逆元
    • 逆元打表求1!~n!

逆元应用与证明

在学习逆元之前我们先来了解一下同余的概念:
简单来讲就是整数a mod(m)=b mod(m) ,写做 a ≡ b ( m o d m ) a\equiv b(mod \ m) ab(mod m)

再来看一下逆元的定义:
简单来说就是: a ∗ x ≡ 1 ( m o d m ) a*x\equiv 1(mod \ m) ax1(mod m) (gcd(a,b)==1,也就是a要与b互质) 这时,我们称 a a a在模 m m m下的逆元为 x x x,同样 x x x的逆元为 a a a,记作 inv( x x x)= a a a

a a a在模 m m m下的逆元存在的充分必要条件是 a a a m m m互质,即gcd(a,m)=1

那么逆元有什么运用呢?
一方面是求余:
(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) %p (错)
这时我们就需要用到逆元来解决了。
那么怎么解决呢?

a ∗ x ≡ 1 ( m o d p ) a*x \equiv 1(mod \ p) ax1(mod p) -----------(1)
那么,在数论上 x = 1 a ( m o d p ) x=\frac{1}{a}(mod \ p) x=a1(mod p)
那么 ( a b ) % p = a ∗ x % p (\frac{a}{b}) \% \ p=a*x\% \ p (ba)% p=ax% p这时就可以直接得出结果了。

我们来证明一下这个结论:
假设 ( a b ) % p = m (\frac{a}{b}) \% \ p=m (ba)% p=m----------(2)

两边同时乘于 b b b a % p = m ∗ b % p a\%p=m*b\%p a%p=mb%p------------(3)

再同时乘与 x x x a ∗ x % p = m ∗ b ∗ x % p a*x\%p=m*b*x\%p ax%p=mbx%p----------(4)//注意这里的x是b(mod p)的逆元,即 b ∗ x ≡ 1 ( m o d p ) b*x \equiv 1(mod \ p) bx1(mod p)

由(1)可得: a ∗ x % p = m % p a*x\%p=m\%p ax%p=m%p---------(5)

所以我们可以得到 ( a b ) % p = a ∗ x % p (\frac{a}{b}) \% \ p=a*x\% \ p (ba)% p=ax% p

那么如何求一个数的逆元呢?
有两种方法:

1.快速幂(费马小定理)
当p为质数时,且a不为p的倍数(a,p一定互质),那么可以用费马小定理来求解,费马小定理指出
当p为质数时,且a不为p的倍数时 a p − 1 ≡ 1 ( m o d p ) a^{p-1}\equiv1(mod\ p) ap11(mod p),左边变形可得
a ∗ a p − 2 ≡ 1 ( m o d p ) a*a^{p-2}\equiv1(mod\ p) aap21(mod p)等价于 a ∗ x ≡ 1 ( m o d p ) , x = a p − 2 a*x\equiv1(mod\ p),x=a^{p-2} ax1(mod p),x=ap2
这里 a a a的逆元inv( a a a)= a p − 2 a^{p-2} ap2,可以用快速幂来求 a p − 2 a^{p-2} ap2
时间复杂度为 O ( l o g n ) O(log n) O(logn)
当p不为质数,但是a,p互质时(不互质逆元不存在),可以根据欧拉定理来求逆元,欧拉定理是对
费马小定理的扩展,用欧拉定理时需要先求欧拉数 φ ( p ) \varphi(p) φ(p),欧拉定理是 a φ ( p ) ≡ 1 ( m o d p ) a^{\varphi(p)}\equiv1(mod\ p) aφ(p)1(mod p),因为质数的欧拉数为其自身-1,所以费马小定理求逆元不用求额外求欧拉数,不过一般p不为质数时,用扩展欧几里得算法来求逆元

扩展欧几里得算法
扩展欧几里得算法就是辗转相除法,在辗转相除时要通过回溯来找系数

费马小定理方法

费马小定理(Fermat’s little theorem)是数论中的一个重要定理,在1636年提出。如果p是一个质数,而整数a不是p的倍数,则有 a p − 1 ≡ 1 ( m o d p ) a^{p-1}≡1(mod \ p) ap11mod p

费马小定理要求 p p p为质数,而逆元的定义要求 g c d ( a , p ) = 1 gcd(a,p)=1 gcd(a,p)=1,所以当我们用费马小定理求解逆元时,前提条件是 p p p为质数,之后只需要保证 a a a不是 p p p的倍数(>=1)即可。
求解方法:
a p − 1 ≡ 1 ( m o d p ) a^{p-1}≡1(mod \ p) ap11mod p=>

a ∗ a p − 2 ≡ 1 ( m o d p ) a*a^{p-2}≡1(mod \ p) aap21mod p

此时a的逆元 x = a p − 2 x=a^{p-2} x=ap2,我们可以利用快速幂来求出 a p − 2 a^{p-2} ap2

模板题:

给定n组ai,pi,其中pi是质数,求ai模pi的乘法逆元,若逆元不存在则输出impossible。

注意:请返回在0∼p−1之间的逆元。

乘法逆元的定义

 若整数b,m互质,并且对于任意的整数 a,如果满足b|a,则存在一个整数x,使得    						a/b≡a∗x(mod m),则称x为b的模m乘法逆元,记为b−1(mod m)b存在乘法逆元的充要条件是b与模数m互质。当模数m为质数时,bm−2即为b的乘法逆元。

输入格式
第一行包含整数n。

接下来n行,每行包含一个数组ai,pi,数据保证pi是质数。

输出格式
输出共n行,每组数据输出一个结果,每个结果占一行。

若ai模pi的乘法逆元存在,则输出一个整数,表示逆元,否则输出impossible。

数据范围

1≤n≤1e5,
1≤ai,pi≤2∗1e9

输入样例:

3
4 3
8 5
6 3

输出样例:

1
2
impossible

分析:这是一道用费马小定理来求逆元的模板题,只需要判断ai是否是pi的倍数,然后用快速幂求出 a i p − 2 {ai}^{p-2} aip2即可。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int n,a,p;
int abc()
{int res=1;int b=p-2;while(b){if(b&1) res=(ll)res*a%p;b>>=1;a=(ll)a*a%p;}return res;
}
int main()
{scanf("%d",&n);while(n--){scanf("%d%d",&a,&p);if(a%p==0) printf("impossible\n");else printf("%d\n",abc());}return 0;
}

扩展欧几里得求逆元

首先了解一下扩展欧几里得算法,扩展欧几里得算法求逆元要保证 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1,条件要比快速幂要宽一些。
a x ≡ 1 ( m o d b ) ax\equiv1(mod\ b) ax1(mod b)
a x − k b = 1 ax-kb\ =1 axkb =1这样是不是就很眼熟了( a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)
事实上就可以写成 a x + b y = 1 ax+by=1 ax+by=1
那么求逆元的方法就有了,就是求解 x \ \ x   x

这里给出扩展欧几里得算法的模板代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
int exgcd(int a,int b,int &x,int &y)
{if(!b){x=1,y=0;return a;}int d=exgcd(b,a%b,y,x);//a,b交换位置,x,y的位置也改变y-=a/b*x;return d;
}
int main()
{scanf("%d",&n);while(n--){int a,b,x,y;scanf("%d%d",&a,&b);int k=exgcd(a,b,x,y);printf("%d %d\n",x,y);}return 0;
}

可以求得 x , y x,y x,y, x x x a a a的逆元。

打表求逆元

用来求1~p-1(mod p)的逆元
递推式:

inv[i] = ( p - p / i ) * inv[p % i] % p

证明:
令 p=k*i+r,其中1<i<p,r<i
则 p ≡ \equiv 0(mod p)
即 k ∗ * i+r ≡ \equiv 0(mod p),两边同时乘于inv[i]和inv[r]可得
k ∗ * inv[r]+inv[i] ≡ \equiv 0(mod p)
inv[i] = -k ∗ * inv[r](mod p),k=p/i(整除)
inv[i] = -p/i ∗ * inv[r](mod p)
要保证inv[i]为正整数,所以inv[i] =(p -p/i) ∗ * inv[r](mod p)
特殊的,inv[1]=1,i从2开始打表

逆元打表求1!~n!

递推公式:
inv[i] = inv[i + 1] * (i + 1) % MOD
反着递推,首先用费马小定理或者扩展欧几里得求出n!的逆元,
n ! − 1 ∗ n = ( n − 1 ) ! − 1 n!^{-1}*n=(n-1)!^{-1} n!1n=(n1)!1,从大到小递推即可


http://www.ppmy.cn/news/382857.html

相关文章

ubuntu 安装网卡驱动

ubuntu 安装网卡驱动 查看当前网卡 # 首先 查看当前所有的 网卡, ifconfig -a # 一定要加 -a (表示all) # 若有显示,说明识别成功,再查看目前已经启动的网卡有没有 ifconfig # 查看目前启动的网卡 (防止识别到了硬件,但没有启动,热插拔未启动的现象)下载相应的驱动 #…

Win10查看网卡驱动的方法

Win10电脑中的网卡驱动出现问题&#xff0c;可以试试卸载重装网卡驱动的方法&#xff0c;那么Win10网卡驱动在哪找呢&#xff1f;下面小编就给大家介绍一下Win10查看网卡驱动的方法&#xff0c;简单几步即可完成。 Win10网卡驱动位置在哪&#xff1f; 1、右击桌面的此电脑&…

台式计算机网卡在哪里查看,网卡驱动在哪里查看,教您如何查看电脑网卡驱动...

一些对电脑还不是很了解的用户问小编&#xff0c;为什么在电脑装完系统后&#xff0c;有时电脑连不上网&#xff0c;是不是没有安装好呢&#xff1f;有或者在安装系统的过程中忘了操作哪一步还是哪个选项选错了呢&#xff1f;要不要重装过系统呢&#xff1f;面对这一连串的疑问…

Java问题二十道

问题 1&#xff1a;什么是Java&#xff1f;它有哪些特点&#xff1f; 答案&#xff1a;Java是一种面向对象的编程语言&#xff0c;具有以下特点&#xff1a; 简单性&#xff1a;Java语法相对简单&#xff0c;易于学习和使用。 面向对象&#xff1a;Java支持面向对象的编程范式…

网卡驱动无法安装怎么办?

最近有用户反映这个问题&#xff0c;没有网卡驱动就没办法上网&#xff0c;安装的时候发现一直安装不上&#xff0c;这是怎么回事呢&#xff1f;针对这一问题&#xff0c;本篇带来了详细的Win7系统网卡驱动无法安装的解决方法&#xff0c;快来看看。 1、最先在桌面&#xff0c;…

debian安装网卡驱动

debian安装网卡驱动 1、安装完debian的时候&#xff0c;你会发现根本就上不了网&#xff0c;你的网卡还没有驱动&#xff0c;所以你也就不用想能apt-get instal ** 2、找一台能上网的机器&#xff0c;到这个地方下载一个bpo包&#xff1a; http://backports.debian.org/debian-…

Linux网卡驱动(1)-网卡驱动架构分析

1.Linux网络子系统 我们这里研究内核空间即可&#xff0c;在内核空间分成5层&#xff0c;分别是&#xff1a; 1、系统调用接口&#xff0c;它面向的客户是应用层序&#xff0c;为应用程序提供访问网络子系统的统一方法&#xff0c;比如说socket,send等函数的系统调用2、协议无关…

网络驱动

工作需要写了我们公司一块网卡的Linux驱动程序。经历一个从无到有的过程&#xff0c; 深感技术交流的重要。Linux作为挑战微软垄断的强有力武器&#xff0c;日益受到大家的喜 爱。真希望她能在中国迅速成长。把程序文档贴出来&#xff0c;希望和大家探讨Linux技术 和应用&#…