同余定理:
    按字面意思来理解,就是两个数除以同一个数m余数相同;
    举个栗子:100%8=4;60%8=4;那么就可以说,100与60对8取模相同,记作:100≡60(mod 8);

逆元:

    如果两个数a和b,a*b对于数m取余和1对m取余相等,即:(a*b)≡1(mod m);就称,b是a的逆元。
    反之,如果已知一个数c是数字b的逆元,即有:(b*c)≡1(mod m);

如何求一个数的逆元:

根据费马小定理求逆元:

    费马小定理:如果p是质数,且数字a与p互质,那么,a^(p-1)≡1(mod p);
    这里有两个条件:1,p必须是质数;2,a不能被p整除。   结论就是,a的p-1次方对p求余等于1;
    那么接下来:
        a^(p-1)1(mod p)
        a*a^(p-2)≡1(mod p)
        所以,在满足条件的情况下,a的逆元就是a^(p-2);只需要用快速幂求一下a的p-2次方。

根据扩展欧几里得求逆元:

贝足定理:

        如果a,b为整数,那么一定存在x,y使得ax+by=gcd(a,b);
    换句话说,就是方程ax+by=m有解,那么m一定是gcd(a,b)的若干倍;
    另,若ax+by=1有解,那么gcd(a,b)=1;

欧几里得算法:

     欧几里得有一个定理:gcd(a,b)=gcd(b,a%b);也就是辗转相除法,求gcd.
辗转相除法:      

int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
扩展欧几里得算法:

#include<iostream>
#include<cstdio>
#include<cmath>
 
using namespace std;
 
int exgcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1;y=0;
        return a;  //到达递归边界开始向上一层返回
    }
    int r=exgcd(b,a%b,x,y);
    int temp=y;    //把x y变成上一层的
    y=x-(a/b)*y;
    x=temp;
    return r;     //得到a b的最大公因数
}

 当到达递归边界的时候,b==0,a=gcd(a,b) 这时可以观察出来这个式子的一个解:a*1+b*0=gcd(a,b),x=1,y=0

扩展欧几里得求逆元:
    a*x≡1(mod m) 等价于a*x+m*y=1可以用扩展欧几里得求得一组解,(x+m)mod m 即为a的逆元。

int cal(int a,int b)
{
	int x,y;
	int gcd=exgcd(a,m.x.y);
	if(1%gcd!=0) return -1;
	x*=1/gcd;
	m=abs(m);
	int ans=x%m;
	if(ans<=0) ans+=m;
	return ans;
}