1.1定义
所谓的同余,顾名思义,就是许多的数被一个数d去除,有相同的余数。d数学上的称谓为模。如a=6,b=1,d=5,则我们说a和b是模d同余的。因为他们都有相同的余数1。
数学上的记法为:
a≡ b(mod d)
可以看出当n 对于同余有三种说法都是等价的,分别为: (1) a和b是模d同余的. (2) 存在某个整数n,使得a=b+nd . (3) d整除a-b. 可以通过换算得出上面三个说法都是正确而且是等价的. 1.2主要性质 1.3应用: 高精度取模 1.3.1高精度对单精度取模 一个高精度数a对一个数b取余,可以把高精度数看成各位数的权值与个位数乘积的和。 比如1234 = ((1 * 10 + 2) * 10 + 3) * 10 + 4,对这个数进行取余运算就是上面基本加和乘的应用。 1.3.2快速幂取模 (详细的快速幂取模https://wenku.baidu.com/view/d65f294702768e9951e73883.html) 将幂拆解为多个底数的平方次的积,如果指数为偶数,把指数除以2,并让底数的平方次取余,如果指数为奇数,就把多出来的底数记录下来,再执行偶数次的操作。 我们先将b按2进制展开假设b = 10, 那么b的二进制为1010,也就是0*2^0+1*2^1+0*2^2+1*2^3 = 10; 所以 a^b = a^(0*2^0+1*2^1+0*2^2+1*2^3 ) = a^(2^1) * a(2^3);这种简单的转换在初中就学过了吧,相信大家都懂 所以a^b%c = a^(2^1) * a(2^3) % c =( a^(2^1) % c) * (a(2^3)%c)%c; 补充:1.同余满足等价关系。具体地说,它满足自反性(一个数永远和自己同余)、对称性(a和b同余,b和a也就同余)和传递性(a≡b(mod d),b≡c(mod d))→a≡c(mod d) 定义:设c是b的逆元,则有b*c≡1(mod m); 限制:a,p互质.p为质数 证明 a*x≡1(mod m) 等价于a*x+m*y=1 可以用扩展欧几里得求 代码实现 - a*x + b*y = 1 如果ab互质,有解 这个解的x就是a关于b的逆元 y就是b关于a的逆元 为什么呢? 你看,两边同时求余b a*x % b + b*y % b = 1 % b a*x % b = 1 % b a*x = 1 (mod b) 你看你看,出现了!!!(/≥▽≤/) 所以x是a关于b的逆元 -----------
数学表述:
加法 (a+b)%c=(a%c+b%c)%c
乘法 (a*c)%c=(a%c*b%c)%c
性质证明(加法)
a = k1*m+r1 ,b = k2*m+r2
(a+b)%m=(( k1*m+r1 )+( k2*m+r2 ))%m
= (( k1+k2 )*m+( r1+r2 ))% m
= (r1+r2 )%m
= (a%m+b%m)% m#include
//给出3个正整数A B C,求A^B Mod C。
例如,3 5 8,3^5 Mod 8 = 3。
#include
2.逆元
推论:(a/b)mod m = (a/b)*1mod m = (a/b)*b*c mod
m=a*c(mod m); 即a/b的模等于a*(b的逆元)的模
2.1费马小定理求解逆元
代码实现,复杂度Olog(n)LL pow_mod(LL a, LL b, LL mod){//a的b次方求余p
LL ret = 1;
while(b){
if(b & 1) ret = (ret * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return ret;
}
LL Fermat(LL a, LL p){//费马求a关于p的逆元
return pow_mod(a, p-2, p);
}
2.2扩展欧几里得
算法作用:求解a,b 最大公约数m 和a*x+b*y=m 的一个解
实现方法:辗转相除法;
采用递归思想,当b=0时停止递归,此时x=1,y=0;回溯后会
得到一组关于二元一次方程的解
考虑两个方程
:a*x1+b*y1=gcd(a,b), b*x2 +(a%b)* y2=gcd(b,a%b)
\ 由辗转相除法可得到gcd(a,b)= gcd(b,a%b)
\ 从而得到a*x1+b*y1=b*x2 +(a%b)* y2
\ 即 a*x1+b*y1=b*x2 +(a -(a/b)*b)* y2
\ =a*y2+b*(x2 -(a/b)* y2)
\ 所以x1=y2 ,y1=x2 -(a/b)* y2.
得一组解,(x+m)mod m即为a的逆元int exgcd (int a, int b, int &x, int &y)
{
if(b == 0)
{//推理,终止条件1
x = 1;
y = 0;
return a;
}
int r = exgcd (b, a%b, x, y);
int t = y;
y = x - (a/b) * y;//相当于y1=x2-(a/b)*y2
x = t; //相当于x1=y2
return r; //最大公约数
}
//返回r=gcd(a,b);和对应于等式ax+by=d中的x,y
//解x就是a关于b的逆元,解y就是b关于a的逆元
//求2对于1e9+7的逆元就是 exgcd(2, 1e9+7, x, y),其中x的值就是inv2
#include