数论入门2——gcd,lcm,exGCD,欧拉定理,乘法逆元,(ex)CRT,(ex)BSGS,(ex)Lucas,原根,Miller-Rabin,Pollard-Rho

Posted ck6100lgev2

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数论入门2——gcd,lcm,exGCD,欧拉定理,乘法逆元,(ex)CRT,(ex)BSGS,(ex)Lucas,原根,Miller-Rabin,Pollard-Rho相关的知识,希望对你有一定的参考价值。

数论入门2

另一种类型的数论...

GCD,LCM

定义(gcd(a,b))为a和b的最大公约数,(lcm(a,b))为a和b的最小公倍数,则有:

将a和b分解质因数为(a=p1^{a1}p2^{a2}p3^{a3}...pn^{an},b=p1^{b1}p2^{b2}p3^{b3}...pn^{bn}),那么(gcd(a,b)=prod_{i=1}^{n}pi^{min(ai,bi)},lcm(a,b)=prod_{i=1}^{n}pi^{max(ai,bi)})(0和任何数的最大公约数是这个数,最小公倍数是0)

显然成立的吧。

所以我们有(gcd(a,b)*lcm(a,b)=ab)

(gcd(a,b))的方法:

首先我们有:(gcd(a,b)=gcd(b,a-b)(a>=b))

显然的啊,两个数相减怎么可能影响他们的最大公约数,毕竟是“公”约数,相减肯定还存在这个因子啊。

所以拓展一下我们就有:(gcd(a,b)=gcd(b,a \% b)(a>=b))

取模就是不断相减,所以也是成立的呀。

所以我们可以写出简洁的代码:

int gcd(int a,int b){return !b?a:gcd(b,a%b);}

很显然这个复杂度是log的,每次至少减少一半。

lcm的话,(a/gcd(a,b)*b)即可。

然后呢,gcd和lcm具有交换律和结合律:

(gcd(a,b,c)=gcd(gcd(a,b),c)=gcd(c,b,a))

所以求多个数的gcd或lcm的时候就可以递推求啦。

还有一个东西就是(gcd(ka,kb)=k*gcd(a,b)),也是显然的。

exGCD

对于方程(ax+by=c),显然若(gcd(a,b)|c)的时候才有解。

因为不整除的话(ax+by)肯定有(c)不包含的因子,那样的话怎么可能有解呢?

然后呢,我们可以通过这样的方式快速借助求gcd的过程求出(ax+by=gcd(a,b))的一组解。

(a=gcd(a,b),b=0)时,显然(x=1,y=0)

(a = b, b = a \% b),则有方程(b *x1 +(a \% b) * y1 = gcd(b, a \% b))

又因为(gcd(a, b) = gcd(b, a \% b)),且(a \% b = a - b * ?a / b?)

(b * x1 + (a - b * ?a / b?) * y1 =gcd(a, b))

整理得:(a * y1 +b * (x1 - ?a / b? *y1) = gcd(a, b))

所以原方程中:(x = y1, y = x1 - ?a / b? *y1)。于是我们只要递归求出(x1, y1)就能求出(x, y)

我们现在已经求得了(ax +by = gcd(a, b))的解,那么对于方程(ax + by = c (gcd(a, b) | c))呢?

因为已经知道(a *x1 +b * y1 = gcd(a, b))的解(x1, y1),左右两边同乘以(c / gcd(a, b)) 得:

(a * x1 * c / gcd(a, b) +b * y1 * c / gcd(a, b) = c)

则原方程的一组解(,x2 = x1 * c / gcd(a, b), y2 = y1 * c / gcd(a, b))

由此得出解集(,{(x, y) | x = x2 + k * b / gcd(a, b), y = y2 - k * a / gcd(a, b), k ∈ Z})

对于线性同余方程(axequiv cquad(modquad b)),我们怎么做呢?

显然可以转化成(ax+by=c)的形式,然后直接用扩欧解决啦。

贴个代码:

ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b){x=1;y=0;return a;}
    ll g=exgcd(b,a%b,y,x);y-=a/b*x;
    return g;
}

欧拉定理

费马小定理:

若p是质数,且(gcd(a,p)=1),则(a^{p-1}equiv1(modquad p))

欧拉定理:

(gcd(a,p)=1),则(a^{varphi(p)}equiv1(nod quad p))

扩展欧拉定理:

(a^bequiv egin{cases} a^{b\%varphi(p)}~~~~~~~~~~~gcd(a,p)=1\ a^b~~~~~~~~~~~~~~~~~~gcd(a,p) eq1,b<varphi(p)\ a^{b\%varphi(p)+varphi(p)}~~~~gcd(a,p) eq1,bgeqvarphi(p) end{cases}~~~~~~~(mod~p))

(varphi)为欧拉函数。

证明:欧拉定理和扩展欧拉定理的证明

有个作用就是在算(a^b)的时候对b进行取模,使运算更高效,具体见luogu欧拉定理模板题

乘法逆元

(gcd(a,b)=1,)(axequiv 1(mod~p)),则称x为a在模p意义下的乘法逆元。

那么求法就很显然了。

欧拉定理:a在模p意义下的逆元为(a^{varphi(p)-1})

exGCD:当做一个同余方程求,但是要通过+kp的方式变为一个正数。

此外还有一个线性求逆元的算法。

首先,1在任何模数下的逆元都是1。

然后设(p=i*k+r,r<i,1<i<p)

那么我们有(i*k+requiv 0(mod~p))

两边同时乘上(i^{-1}*r^{-1})得:

(k*r^{-1}+i^{-1}equiv 0(mod~p))

(i^{-1}equiv -k* r^{-1}(mod~p))

因为(k=lfloor p/i floor,r=p\%i),所以我们得到了逆元的递推式:

a[i]=-(p/i)*a[p%i]%p;

以及提一句,逆元是完全积性函数,从定义式里面就能看出来。

对于一个前缀积的序列的话,我们可以求出最后一项的逆元,然后(O(n))递推回去,实际上逆元可以理解为模意义下的(frac{1}{x}),怎么递推的话也很显然了,以阶乘为例:

fac[0]=1;
for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%P;
ifa[n]=ksm(fac[n],P-2);
for(int i=n-1;~i;i--) ifa[i]=ifa[i+1]*(i+1)%P;

还有就是:

((a/b)\%p=(a\%(bp))/ p)

证明:

((a/b)\%p=a/b-?(a/b)/p?*p)

(=a/b-?a/(b*p)?*p)

(=a/b-?a/(bp)?*b*p/b)

(=(a\%(bp) )/p)

CRT

已知系数全部为1的线性同余方程组:

(x equiv a_i(mod ~p_i)),其中(p_i)两两互质,求x的最小非负整数解。

那么我们考虑这样一个思路:

从1到n考虑每个同余方程组,我们设(M=prod_{i=1}^{n}p_i),那么当我们考虑到第i个方程的时候,我们设(T=frac{M}{p_i}),那么我们发现把第i个方程的解(x)加上(kT)的话,(x+kT)带到别的同余方程组的余数不会改变。

假设我们已经求出了前(i-1)个方程的通解(x),求出了第(i)个方程的一个解(x_i),那么显然,(Tx_i+x)是前(i)个方程的解。

我们用exGCD求出第i个线性同余方程组(Tx_iequiv a_i(mod~p_i))的解,一步步合并即可,因为(p_i)显然和(T)互质,所以实际上是求出逆元之后乘上(a_i)

exCRT

已知系数全部为1的线性同余方程组:

(x equiv a_i(mod ~p_i)),其中(p_i)都是正整数,求x的最小非负整数解。

上面的算法失效了。为什么?都不一定互质了怎么可能还去求逆元?

所以我们要考虑一个新的思路:

假设我们已经求出了前(i-1)个方程的通解(x),设(M)为前i-1个数的lcm,那么我们发现(x+kM)如果能够满足第(i)个方程,那么前i个方程就都解出来啦。

我们写个式子:(x+kM equiv a_i(mod~p_i)),移项得(kM equiv a_i-x(mod ~p_i))

那么我们解出来k之后,前i个方程的通解就出来啦,一步步做下去即可。

贴个代码:

ll mul(ll x,ll y,ll p){ll g=0;for(;y;y>>=1,x=(x+x)%p) if(y&1) g=(g+x)%p;return g;}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b){x=1;y=0;return a;}
    ll g=exgcd(b,a%b,y,x);y-=a/b*x;
    return g;
}
for(int i=1;i<=n;i++) scanf("%lld%lld",&b[i],&a[i]);
ans=a[1];M=b[1];
for(int i=2;i<=n;i++)
{
    ll A=M,B=b[i],c=(a[i]%B-ans%B+B)%B,x,y;
    ll gcd=exgcd(A,B,x,y),d=B/gcd;
    if(c%gcd) return 0;x=mul(x,c/gcd,d);
    ans+=x*M;M*=d;ans=(ans%M+M)%M;
}

注意一下,因为是求lcm,所以那个B要除以gcd。

BSGS

exBSGS

原根

Lucas

exLucas

Miller-Rabin

Pollard-Rho

以上是关于数论入门2——gcd,lcm,exGCD,欧拉定理,乘法逆元,(ex)CRT,(ex)BSGS,(ex)Lucas,原根,Miller-Rabin,Pollard-Rho的主要内容,如果未能解决你的问题,请参考以下文章

hdu4497-GCD and LCM-(欧拉筛+唯一分解定理+组合数)

gcd以及exgcd入门讲解

数论小节

欧几里得(辗转相除gcd)扩欧(exgcd)中国剩余定理(crt)扩展中国剩余定理(excrt)简要介绍

数论初步——欧几里得算法和唯一分解定理

欧拉定理数论