逆元

知识点

因数和倍数的性质

a ∣ b a|b ab在数学中表示a是b的因数。
关于符号"|",有以下性质:

  1. 如果 a ∣ b a|b ab则有 − a ∣ b -a|b ab , a ∣ − b a|-b ab , ∣ a ∣ ∣ ∣ b ∣ |a| | |b| a∣∣∣b
    推导过程: a ∣ b a|b ab就是 b / a = k b/a=k b/a=k,在正数与负数的除法中,改变一个整除算式中的数前的正负号,不过改变商的正负号,依然能整除,因此此性质成立。
  2. 如果 m ≠ 0 , a ∣ b m\neq0,a|b m=0,ab则有 m a ∣ m b ma|mb mamb
    推导过程: a ∣ b a|b ab就是 b / a = k b/a=k b/a=k, m a ∣ m b ma|mb mamb就是 m b / m a = k mb/ma=k mb/ma=k,根据除法商不变的性质:除数和被除数同时乘或除以相同的数(0除外),商不变,可知此性质成立。
  3. 如果 a ∣ b , b ∣ c a|b,b|c ab,bc则有 b ∣ c b|c bc
    推导过程: a ∣ b = 1 a ∣ a x , b ∣ c = a x ∣ a x y , x = b / a , y = c / b a|b=1a|ax,b|c=ax|axy,x=b/a,y=c/b ab=1aax,bc=axaxy,x=b/a,y=c/b a ∣ c = a ∣ a x y a|c=a|axy ac=aaxy,显然 a x y % a = 0 axy\%a=0 axy%a=0
  4. 如果 a ∣ b , a ∣ c a|b,a|c ab,ac则有 a ∣ ( b x + c y ) a|(bx+cy) a(bx+cy)(x,y为任意自然数)
    推导过程: a ∣ b = 1 a ∣ a n , a ∣ c = 1 a ∣ a m , n = b / a , m = c / a a|b=1a|an,a|c=1a|am,n=b/a,m=c/a ab=1aan,ac=1aam,n=b/a,m=c/a a ∣ ( b x + c y ) = a ∣ ( a n x + a m y ) = a ∣ a ( n x + m y ) a|(bx+cy)=a|(anx+amy)=a|a(nx+my) a(bx+cy)=a(anx+amy)=aa(nx+my),显然 a ( n x + m y ) % a = 0 a(nx+my)\%a=0 a(nx+my)%a=0
  5. 如果 ( m , a ) = 1 , m ∣ a b (m,a)=1,m|ab (m,a)=1,mab则有 m ∣ b m|b mb
    推导过程: ( m , a ) = 1 (m,a)=1 (m,a)=1说明 m ∣ a b m|ab mab与a一点关系都没有,则 m ∣ a b = m ∣ a m k , m ∣ b = m ∣ m k m|ab=m|amk,m|b=m|mk mab=mamk,mb=mmk,显然 m k % m = 0 mk\%m=0 mk%m=0
  6. 有一个集合a长度为n,如果 a i ∣ c , ( 1 ≤ i ≤ n ) a_i|c,(1\leq i \leq n) aic,(1in)则有 [ a 1 , a 2 , . . . , a n ] ∣ c [a_1,a_2,...,a_n]|c [a1,a2,...,an]c
    推导过程: a i ∣ c a_i|c aic说明c是所有 a i a_i ai的倍数,也就是它们的公倍数,一些数的公倍数是这些数的最小公倍数的倍数,因此此性质成立
  7. 如果 a = b q + r a=bq+r a=bq+r a ∣ b a|b ab的充分必要条件为 r = 0 r=0 r=0
    推导过程: a = b q + 1 − > a / b = q . . . . . . r , r = 0 a=bq+1->a/b=q......r,r=0 a=bq+1>a/b=q......r,r=0 a = b q + 1 − > a / b = q a=bq+1->a/b=q a=bq+1>a/b=q,显然此性质成立

取模的四则运算

加法:
( A + B ) % m o d = ( ( A % m o d ) + ( B % m o d ) ) % m o d (A + B) \% mod = ((A \% mod) + (B \% mod)) \% mod (A+B)%mod=((A%mod)+(B%mod))%mod
乘法:
( A ∗ B ) % m o d = ( ( A % m o d ) ∗ ( B % m o d ) ) % m o d (A * B) \% mod = ((A \% mod) * (B \% mod)) \% mod (AB)%mod=((A%mod)(B%mod))%mod
减法(由于在进行减法运算后结果可能是负数,因此需要加上一个mod后再取模):
( A − B ) % m o d = ( ( A % m o d ) − ( B % m o d ) + m o d ) % m o d (A - B) \% mod =((A \% mod) - (B \% mod) +mod) \% mod (AB)%mod=((A%mod)(B%mod)+mod)%mod
除法运算取模是不是也和上面的取模运算一样是
( A / B ) % m o d = ( ( A % m o d ) / ( B % m o d ) ) % m o d (A / B) \% mod = ((A \% mod) / (B \% mod)) \% mod (A/B)%mod=((A%mod)/(B%mod))%mod呢?
答案是否定的,除以一个数可以看成乘这个数的倒数,这个数也叫做逆元,x的逆元记作 i n v ( x ) , x − 1 inv(x),x^{-1} inv(x),x1。.
所以 ( A / B ) % m o d = ( ( A % m o d ) ∗ ( B − 1 % m o d ) ) % m o d (A / B) \% mod = ((A \% mod) * (B^{-1} \% mod)) \% mod (A/B)%mod=((A%mod)(B1%mod))%mod

逆元的定义和意义

数学上认为mod就是在一个环上做运算,如:x mod 5,认为是在下图中做运算,可是要是运算数中出现分数,并不在环上怎么办?

0
1
2
3
4

分数可以看成除法,除以一个数可以看成乘这个数的倒数,关于取模的倒数叫逆元,x的逆元记作 i n v ( x ) , x − 1 inv(x),x^{-1} inv(x),x1
要使 ( a ∗ a − 1 ) % p = 1 (a*a^{-1}) \% p=1 (aa1)%p=1 a % p = a − 1 % p a \% p = a^{-1} \% p a%p=a1%p

逆元的计算

根据费马小定理得知:
(p为质数,a不是p的倍数)
a p − 1 % p = 1 a^{p-1} \% p=1 ap1%p=1
经过变形可得
( a ∗ a p − 2 ) % p = 1 (a*a^{p-2}) \% p=1 (aap2)%p=1
( a ∗ a − 1 ) % p = 1 (a*a^{-1}) \% p=1 (aa1)%p=1相似
因此 a − 1 = a p − 2 a^{-1}=a^{p-2} a1=ap2

题目

求逆元

时间限制:1秒 内存限制:128M

题目描述

输入a,b= 1 0 9 + 7 10^9+7 109+7,求 a % b a\%b a%b时inv(a)

样例输入

3

样例输出

333333336

代码

用公式解答即可

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
long long mod=1e9+7,a;
long long fast_pow(long long a,long long b){
	long long fac=1;
	while(b>0){
		if(b&1){
			fac*=a;
			fac%=mod;
		}
		a=a*a;
		a%=mod;
		b>>=1;
	}
	return fac%mod;
}
int main() {
    scanf("%lld",&a);
	printf("%lld",fast_pow(a,mod-2));
    
    return 0;
}

线性求逆元

时间限制:1秒 内存限制:128M

题目描述

给定n,p,求1到n所有整数在模p意义下的乘法逆元。

样例输入

10 13

样例输出

1
7
9
10
8
11
2
5
3
4

思路

(p/x向下取整)
i n v ( x ) inv(x) inv(x)还等于 ( p − p / x ) ∗ i n v ( p % x ) (p-p/x)*inv(p\%x) (pp/x)inv(p%x)
可用此式子递推求逆元,时间复杂度O(n)。

代码

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int n,p;
long long inv[5000005];
int main(){
	scanf("%d %d",&n,&p);
	inv[1]=1;
	printf("%din",inv[1]);
	for(int i=2;i<=n;i++){
		inv[i]=(p-p/i)*inv[p%i]%p;
		printf("%d\n", inv[i]);
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值