关于逆元(费马小定理,exgcd)

1.逆元是个什么东西
首先这里有个式子: ( ( ( a b \frac{a}{b} ba ) ) ) m o d mod mod p p p,这个式子的答案怎么求呢??
A 直接求不行吗?
Q别想了不能。我们发现一个分数 mod 一个整数时是不能直接模运算的,但是可以进行乘法运算,我们就要用到逆元(大概可以看做一个数%p意义下的倒数吧)
除以一个数模 p p p,就等于乘以一个数在mod p意义下的逆元
也就是说,它的定义可以表示为 a x ≡ 1 ax≡1 ax1 ( m o d (mod (mod n ) n) n)
2. 求逆元的方法之——费马小定理

  1. 费马小定理:对于整数 a 与质数 p ,若 a 与 p 互质,则有: a p − 1 ≡ 1 a^{p−1}≡1 ap11 m o d mod mod p p p
  2. 求逆元: a p − 1 ≡ 1 a^{p−1}≡1 ap11 m o d mod mod p p p a p − 2 ∗ p ≡ 1 a^{p−2}*p≡1 ap2p1 m o d mod mod p p p,所以 a p − 2 a^{p−2} ap2 a a a m o d mod mod p p p意义下的逆元
  3. 代码(就是个快速幂)
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
ll a,b,p,r;
ll n;
ll ksm(ll a,ll b,ll p)
{
	ll r=1;
	while(b)
	{
		if(b&1)r=r*a%p;
		b>>=1;
		a=a*a%p;	
	}
	return r;
}
int main()
{
	cin>>n>>p;
	for(int i=1;i<=n;i++)
{
		ll hh=ksm(i,p-2,p);
	cout<

3.方法二——扩展欧几里得

  1. exgcd可以用来判断并求解形如 a x + b y = c ax+by=c ax+by=c 的方程,当且仅当 g c d ( a , b ) ∣ c gcd(a,b)∣c gcd(a,b)c,存在整数解 x , y x,y x,y
  2. 证明:扩欧证明
  3. 求逆元:
    m m m a a a的逆元,那么有 a m ≡ 1 ( am≡1( am1( m o d mod mod p ) p) p)
    那么显而易见地我们可以写成 a m − p n = 1 am-pn=1 ampn=1
    然后就可以exgcd解啦
  4. 代码
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
void read(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
    while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
    x=f*x;
}
int n,p;
void exgcd(int a,int b,int &x,int &y)
{
	int t;
	if(b==0)
	{
		x=1;y=0;return;
	}
	exgcd(b,a%b,x,y);
	t=x;x=y;y=t-(a/b)*y;
}
int main()
{
	read(n);read(p);
	register int x,y;
	for(int i=1;i<=n;i++)
	{
		exgcd(i,p,x,y);
		cout<<(x+p)%p;
		putchar('\n');
	}
}

4.线性求逆元
虽然已经有2种方法,但是对于这样的题模板还是会 T T T
于是我们不得不学习线性逆元
就可以使用递推法 。

i i i p p p 意义下的逆元 i n v ( i ) inv(i) inv(i)可表示为 :

i n v ( i ) = − ⌊ p i ⌋ × i n v ( p % i ) % p \large inv(i) = -\lfloor \frac{p}{i}\rfloor \times inv(p\% i)\% p inv(i)=ip×inv(p%i)%p

#include
#include
#include
#include
#include
#define ll long long
using namespace std;
void read(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
    while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
    x=f*x;
}
int n,p;
ll a[5000005];
int main()
{
	read(n);read(p);
	a[1]=1;
	for(int i=2;i<=n;i++)
	{
		a[i]=(ll)p-(p/i)*a[p%i]%p;
	}
	for(int i=1;i<=n;i++)
	printf("%d\n",a[i]);
}

没 了 q w q 没了qwq qwq
康娜酱!!!!!!
关于逆元(费马小定理,exgcd)_第1张图片

你可能感兴趣的:(数论)