【笔记】逆元简单操作
数论--逆元
2020.1.20 by li'ao老师
功能引入
加、减、乘都可以随时取模,那除以呢?
我们让模意义下除以一个数等于乘他的逆元
定义
如果xy≡1(mod n),则在模n意义下,y为x的逆元,记为x^-1
(逆元可能有多个)
逆元的存在性
x在模n意义有逆元当且仅当(x,n)=1
证:
xy ≡ 1(mod n)
存在k使xy=kn+1
=>xy-kn=1
满足形式ax+by=gcd(x,y)
此时gcd(x,n)=1
寻找逆元
1.exgcd
xy ≡ 1(mod n)
xy=kn+1
xy-kn=1
满足形式ax+by=gcd(x,y)
故可以通过exgcd找逆元
2.线性求逆元
逆元的其他求法:线性求逆元
设n是一个质数,那么1到n-1都与n互质,因此1到n-1在模n意义下都有逆元
1的逆元为1
对x(1<x<n)求逆元
设a=⌊n/x⌋,b=n%x
n=a*x+b
b=-a*x(在模n意义下)
inv[b]*b=-inv[b]*a*x
1≡-inv[b]*a*x(mod n)
-inv[b]*a即为x的逆元
x的逆元可以用比他小的数的逆元得到
递推可以求得1到n-1在模n意义下的逆元
int a = n / x;
int b = n % x;
\[inv[x]=-a*inv[b]
\]
求1~n在模p意义下的逆元
int inv[N] , n , p;
cin >> n >> p;
inv[1]=1;
for (int i = 2 ; i <= n ; i++)
{
int a = p / i;
int b = p % i;
inv[i] = (p - inv[b]*a) % p;
}
版子题
AC代码
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 3000010
#define M 100010
using namespace std;
long long inv[N],n,p;//注意开longlong
inline int read(){
int f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
int main()
{
cin>>n>>p;
inv[1]=1;
for(int i=2;i<=n;i++)
{
int a=p/i;
int b=p%i;
inv[i]=(p-a)*inv[b]%p; //随时取模注意正化
//inv[i]=(p - a*inv[b] )%p 会负
// if(inv[i] < 0)
// {
// cout << i << ' ' << inv[i] << endl;
// break;
// }
//若i是p的因数,则b==0
//若i与n不互质,b为p的因数 ??
}
for(int i=1;i<=n;i++)
printf("%d\n",inv[i]);
//cout TLE
return 0;
}