在 log 的时间内,求出 x 和 y 的最大公约数
首先,设 x 为 a , b 的最大公约数,即 (a,b)=x ,那么 a=k1∗x , b=k2∗x ,则 a mod b=(k1 mod k2)∗x 。
所以, x 也一定是 b 和 a mod b 的最大公约数(因为如果 k2 和 k1 mod k2 的最大公约数不等于 1 ,那么, k2 和 k1 的最大公约数也不等于 1 【这个应该不用我证明吧】,则 x 一定不是 a 和 b 的最大公约数,与定义矛盾了),然后,就把 b 看成 a , a mod b 看成 b ,(很显然,改变后的 b=k2∗x 里的 k2 会变小,因为 k1 mod k2 的值在 0 ~ k2−1 之间)继续递归,又因为 (y,0) 的值就是y(这个应该就不需要证明了吧),所以只要递归到 (y,0) 就可以了。
(证明不是很严谨。。。网上的证明自己看得也是很糊涂,还是喜欢自己证明一遍。)
int gcd(int a,int b)
{
return (b==0?a:gcd(b,a%b));
}
在 log 的时间内,找到 x,y 的最大公约数
在 log 的时间内,找出构成 (a,b) 的 x 和 y 使得 ax+by=(a,b) (或找出构成 (a,b) 的 k 倍的数的 x 和 y ,就是把前面得出的 x 和 y 乘上 k )
在 log 的时间内,找出 a 在模 b 意义下的模反元素(如果, (a,b)=1 ,说明有模反元素为 x ,否则没有)
(弱弱地问一句,模反元素与逆元的区别是什么?【自我感觉是一样的,但是不知道为什么有两个名称】)
原式 :ax+by=(a,b) ,假设 (a≥b)
① 当 b=0 时, (a,b)=a ,即 x=1,y=0 ;
② 当 b≠0 时,根据欧几里得定理 (a,b)=(b,a mod b) 得到 ax+by=bx′+(a mod b)y′
即 ax+by=bx′+(a−b∗⌊a/b⌋)∗y′
移项得到 ax+by=a∗y′+b(x′−⌊a/b⌋∗y′)
然后就可以得到 x=y′ , y=x′−⌊a/b⌋∗y′
然后通过回溯,得出 x , y
int exgcd(int a,int b,int &x,int &y)
{
if (b==0)
{
x=1;y=0;return a;
}
int w=exgcd(b,a%b,x,y),t=x;
x=y;y=t-a/b*y;
return w;
}
在log的时间内求出 x 在模 p ( p 为素数)意义下的逆元
判断一个数是不是素数(即费马素性检验,一个随机化算法判断一个数是否是素数,但是有Carmichael数,会导致判断错误)
(丢个度娘的链接:费马素性检验、Carmichael数)
当模p不是素数的时候需要用到欧拉定理(欧拉定理什么的我还不会…)
方法①:
首先,如果 p 是素数,那么 (p−1)!≡1(mod p) (这个应该不用我证明,表示自己懒的一批,能少写就少写吧)
假设, p 为素数 (x mod p,p)=1 (即费马小定理的前提, x mod p 是保证 x<p )
即对于 f(i)=(x∗i) mod p ( i∈N∗且i≤p−1 )中任意两个不相同的 i , f(i) 的值都不相同
则 (p−1)!≡(x∗1)∗(x∗2)∗(x∗3)∗…∗(x∗(p−2))∗(x∗(p−1))(mod p)
即 (p−1)!≡x(p−1)!∗(p−1)!(mod p)
两边同时除去 (p−1)! (当且仅当一个数为与模数互质时才满足消去性质)就可以得到 xp−1≡1(mod p)
然后就可以得到 x∗x(p−2)≡1(mod p) ,很显然 x(p−2) 就是 x 在模 p 意义下的逆元
方法②:
需要用到后面介绍的欧拉-费马定理,因为 p 为素数,那么很显然 ϕ(p)=p−1 ,那么就可以得出 x(p−1)≡1(mod p)
//等我学会欧拉函数再来写p非素数的费马小定理求逆元
LL pow(LL x,LL n,LL p)//快速算出x^n模p(为素数)后的值,求逆元的话,就是n=p-2
{
LL res=1;
while(n)
{
if (n&1) res=res*x%p;
x=x*x%p;
n>>=1;
}
return res;
}
当需要求逆元的次数过多时就需要打个逆元表,这时候就需要用递推在 n 的时间内求出 1 ~ n 在模 p 意义下的逆元
首先, inv[1]=1 (这个不用证明吧……)
然后,设 x=p/i , y=p mod i
那么,很显然, x 和 y 满足 x∗i+y=p ,即 x∗i+y≡0(mod p)
根据同余的性质,可以得到 y≡−x∗i (mod p) ,然后两边同时除去 y∗i ,得到 inv[i]≡−x∗inv[y] (mod p)
把 x=p/i , y=p mod i 带入得到 inv[i]≡(−p/i∗inv[p mod i]) (mod p)
再根据同余的性质,得到 inv[i]=(p−p/i)∗inv[p mod i] (mod p)
void makeinv(int n,int p)
{
inv[1]=1;
for (int i=2;i<=n;i++) inv[i]=(p-p/i)*inv[p%i]%p;
}
求逆元,尤其是求 p 不是素数,但 (x,p)=1 的 x 的逆元
首先,得知道一个定义: ϕ(p) 为小于 p 的且与 p 互质的正整数的个数(其中,规定 ϕ(1)=1 )
设小于 x 且互质的数从小到大排序后,分别为 a[1]、a[2]、…、a[ϕ(p)] ,那么 (a[1]∗a[2]∗…∗a[ϕ(p)],p)=1
那么, x∗a[1]、x∗a[2]、…、x∗a[ϕ(p)] 在模 p 意义下肯定不同余,且与 p 互质
① 证明不同余:
假设存在同余,那么就等于存在 i 和 j ( i<j )满足 p|x∗(a[j]−a[i])
因为 0<a[j]−a[i]<p ,那么就可以从这里推出 (x,p)≠1 ,与定义矛盾了;
② 证明互质:
假设至少有一个数不与 p 互质
设 r=x∗a[i] mod p 存在 i 满足 (r,p)=y ( y≠1 ),即 x∗a[i]=k∗p+r=y∗((k∗p+r)/y)) 【后面这个数很显然是个整数】,从这里就可以推出 (x,p)≠1 ,与定义矛盾
经过上述的证明后,可以证明 x∗a[1]、x∗a[2]、…、x∗a[ϕ(p)] 这些数与原来的那些未乘过 x 的数在模 p 意义下的值一一对应
(因为,小于 p 且与 p 的数仅有 ϕ(p) 个,而乘 x 以后的数在模 p 意义下不同余且与 p 互质)
所以, (x∗a[1])∗(x∗a[2])∗…∗(x∗a[ϕ(p)])≡a[1]∗a[2]∗…∗a[ϕ(p)]
两边同时除去 a[1]∗a[2]∗…∗a[ϕ(p)] (当且仅当一个数为与模数互质时才满足消去性质)得到 xϕ(p)≡1(mod p)
这个式子也可以转换为 x∗xϕ(p)−1≡1(mod p) ,显然 x 在模 p 意义下的逆元就是 xϕ(p)−1 。
与费马定理差不多,就是多了一个求 ϕ(p)的过程 ,代码就懒得打了。。。
差点忘记介绍欧拉函数的两种做法,一种就是求与其互质数的个数(暴力…),还有一种就是求 x 不同的质因子,那么 ϕ(x) 就等于 (x−x/pi) ( p[i]表示x不同的质因子 )
在 logp(n)∗p 的时间内得到 Ckn 的值
设 n=s∗p+q,k=t∗p+r ,其中, q<p,r<p,p 为素数
首先,得知道当 0<k<p 时, Ckp≡0 (mod p)
因为, Ckp 一定是一个整数,且等于 p!/(k!∗(p−k)!) ,显然当 p 为素数时,在整除的过程中不会被除掉,即 Ckp mod p=0
因为 (1+x)s∗p+q<=>∑i=0s∗p+qCis∗p+q∗xi …………①
而对于 (1+x)n<=>(1+x)s∗p+q<=>((1+x)s)p∗(1+x)q<=>((1+x)p)q∗(1+x)q
所以, (1+x)s∗p+q<=>∑i=0sCis∗xi∗p∗∑i=0qCjq∗xj …………②
对于①式中的 xt∗p+r 的系数为 Ct∗p+rs∗p+q
对于②式中的 xt∗p+r 的系数(因为 p > r ,那么 i∗p+j=t∗p+r 的表达方式唯一)为 Cts∗Crq ,即为 Ck/pn/p∗Ck mod pn mod p
所以, Ck/pn/p∗Ck mod pn mod p≡Ct∗p+rs∗p+q (mod p)
Lucas定理得证
LL pow(LL x,LL n,LL p)
{
LL res=1;
while (n)
{
if (n&1) res=(res*x)%p;
x=(x*x)%p;
n>>=1;
}
return res;
}
LL C(LL n,LL k,LL p)
{
LL ret=1;
while (n&&k)
{
LL q=n%p,r=k%p;
if (q*fact [q]*pow(fact[r]*fact[q-r]%p,p-2,p)%p; //fact(x)表示x!
n/=p;k/=p;
}
return ret;
}
表示自己不知道…求大佬告诉我(别告诉我就是定理的内容…)
对于证明一个素数 p 满足 (p−1)!≡−1 (mod p) ,即证明 (p−1)!≡p−1 (mod p) 对于 2 ~ p−2 内任何数都互相配对互成逆元,且没有一个数会同时与两个不同的数互成逆元
首先,我们可以知道素数中唯一个偶数 2 满足该条件,那么我们只需要证明剩下所有的奇素数即可
对于一个奇素数, 2 ~ p−2 中所拥有的数字的个数一定是偶数个,然后就是证明这些数字互相配对且互成逆元,且没有一个数会同时与两个不同的数互成逆元
根据乘法逆元的定义(乘法逆元,是指数学领域群 G 中任意一个元素 a ,都在 G 中有唯一的逆元 a )可以知道一定没有一个数同时与两个不同的数互成逆元(至于为什么,我表示并不知道)
因为,对于一个数 x 以及它的逆元 y 肯定满足 x∗y≡1 (mod p) ,那么对于 y 来说 x 必定是它的逆元,因为 x∗y≡1 (mod p)<=>y∗x≡1 (mod p)
所以,奇素数中, 2 ~ p−2 中的偶数个数一定互相配对互成逆元(因为 p−1 的逆元为 p−1 【 (p−1)∗(p−1)=p2+2∗p+1≡1 (mod p) 】, 1 的逆元为 1 ,不会对这些数的匹配造成影响),且没有一个数会同时与两个不同的数互成逆元
所以,素数 p 一定满足 (p−1)!≡−1 (mod p)