【笔记】逆元简单操作

数论--逆元

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;
}

版子题

【P3811 【模板】乘法逆元】

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;
}

逆元求组合数

posted @ 2020-01-20 19:03  _Buffett  阅读(221)  评论(1编辑  收藏  举报