先明白扩展欧几里得求不定方程:https://blog.csdn.net/A_Pathfinder/article/details/88131225
再放个逆元整理的:https://blog.csdn.net/weixin_41162823/article/details/82824988?tdsourcetag=s_pctim_aiomsg
同余的定义:给出一个正整数m和两个整数a,b,如果( (a-b)%m )==0,则称a和b模m同余,反之记作a和b不同余m;
例如 -7≡-1≡1≡5≡9(mod 4);记作a≡b(mod m);
定理1:对于( (a-b)%m )==0,当且仅当存在整数k,a=b+k*m;
2:在一个同余式两边同时做加法,减法或者乘法,依然保持同余。(没有除法)
3:对于正整数m和整数a,b,c,d=gcd(c,m),并且ac≡bc(mod m)。则a≡b(mod(m / d) )。例:m=4,a=3,b=1,c=6,gcd(c,m)=gcd(6,4) = 2;并且6*3≡6*1(mod 4)。则3≡1(mod 2)。(用这个求同余方程)
再给出一些运算规则:
(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;
( (a+b)%p + c )%p = (a+(b+c)%p)%p; ( (a*b)%p*c )%p = (a*(b*c)%p)%p; (结合律)
(a+b) %p =(b+a)%p; (a*b)%p=(b*a)%p (交换律)
( (a+b)%p *c)%p = ( (a*c)%p + (b*c)%p )%p (分配律)
练习题:poj 1995
下面是求同余方程:
定义:形如ax≡b(mod m)是同余方程。
定理:gcd(a,m)=d。如果 b mod d !=0;则方程无解,否则恰好有d个模m不同余的解。
注:这里其实可以看作是 ax=b+ym, ax-ym=b,就可以换成exgcd求不定方程了,没看着的那么恶心,然后用exgcd求不定方程的解的定理b%gcd(a,m)来判断解的个数,要注意的是x= x0+k*(b / gcd(a,m) ) ; y= y0+k*(a / gcd(a,m) ); 因为是ax-ym的解。
定理2(求逆元):gcd(a,m)=1,称ax≡1(mod m)的一个整数解为a模m的逆;
注:也就是若a*x≡1(mod m),a*x-m*y=1 ,a,m互质(所有解都模m同余),则称x为a关于m的逆元,逆类似与倒数的概念类似。
除法模运算:设c为b在对P取模状态下的逆元,在求(a/b)%P时,很可能会因为b过大而超过精度范围,这时候可以将除法转换成乘法来做,(a/b)%P = (a*Invb)%P =( (a%P)*(Invb%P)%)P。
例:假设x是a的逆元,a^-1≡x(mod m)等价与ax≡1(mod m);x等价与a^-1,可以带3 ,11,得出x为4,4就是满足于3关于11的逆元。
模板代码:
#include<bits/stdc++.h>
using namespace std;
int exgcd(int a,int b,int &x,int &y){
if(b==0){
x=1;y=0;
return a;
}
int t=exgcd(b,a%b,y,x);
y-=a/b*x;
return t;
}
int get_inv(int a,int m){ //a*x=1(mod m) b是1
int d,x,y;
d= exgcd(a,m,x,y);
if(d==1)//a,b互素
return (x%m+m)%m;
else
return -1;
}
int main(){
int a,b,m;//对于求a的逆元,只要保证ax-my=b,b=1&&gcd(a,m)=1
cin>>a>>m; //b不等于1就是普通的解不定方程
//cout<<get_inv(a,m);
int inva = get_inv(a,m);
if(inva!=-1) printf("a的逆元为:%d",inva);
else cout<<"a无逆元";
return 0;
}
例题:ZOJ 3609