【数论基础】整除,同余初步,欧几里得和扩欧

这篇很杂,我是按照老师讲课顺序打的博客。分别来讲讲

1.整除

a除以非0整数b商为整数,且余数为零,我们就说a能被b整除或说b能整除a,记作b|a。
 
可整除性的基本性质
若a|b, a|c, 则a|(b+c)
若a|b, 那么对所有整数c, a|bc
若a|b, b|c, 则a|c
整除关系具有传递性.

2.同余

a为整数,d为正整数,那么有惟一的整数qr,其中0≤r<d,使得a=dq+r
可以用这个定理来定义除法:d叫除数,a叫被除数,q叫商,r叫余数。
如果两个数a,b除以一个数c的余数相等,说ab关于模c同余,记作ab(mod c)
ab(mod c)成立的充要条件是c|(a-b)

3.欧几里得算法

先是最大公约数和最小公倍数,分别用gcd(a,b)和lcm(a,b)表示

那么有a*b==gcd(a,b)*lcm(a,b)

证明:由

可得

那么当我们要求lcm时,可以先求gcd,再求lcm。

 

再介绍欧几里得算法,又称辗转相除法,古老而强大。

而这是利用了公式gcd(a, b)=gcd(b, a mod b),

时间复杂度为O(logb)
证明:
第一步:令c=gcd(a,b),则设a=mc,b=nc 
第二步:可知r =a-kb=mc-knc=(m-kn)c 
第三步:根据第二步结果可知c也是r的因数 
第四步:可以断定m-kn与n互素【否则,可设m-kn=xd,n=yd,(d>1),则m=kn+xd=kyd+xd=(ky+x)d,则a=mc=(ky+x)dc,b=nc=ycd,故a与b最大公约数≥cd,而非c,与前面结论矛盾】 
从而可知gcd(b,r)=c,继而gcd(a,b)=gcd(b,r),得证
代码很简单:
inline int gcd(int a,int b){return b?gcd(b,a%b):a;}//辗转相除 

4.扩展欧几里得

裴蜀定理:对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。

而扩展欧几里得就是来求这里的x和y的

欧几里得算法的终止条件是x=1,y=0。

先理解一个思路:

设x,y和x1,y1是两组解,且满足:
n由 a*x+b*y = gcd(a,b)
a*x1+b*y1 = gcd(a,b)=gcd(b,a%b)=b*x1+(a%b)*y1
n得 a*x+b*y=b*x1+(a%b)*y1
n设k=a/b,r=a%b,则r=a-k*b,代入上式得
na*x+b*y=b*x1+(a-a/b*b)*y1
na*x+b*y=a*y1+b*(x1-a/b*y1)
n得 x=y1  y=x1-a/b*y1
 
那么递归的更新条件就是x=y1,y=x1-a/b*y1
代码:
inline void ex_gcd(int a,int b){//扩展欧几里得 
    if(b==0){x=1;y=0;return ;}
    ex_gcd(b,a%b);
    int t=x;x=y;y=t-a/b*y;
}
或者
inline int ex_gcd(int a,int b){
    if(b==0){x=1;y=0;return a;}
    int tmp=ex_gcd(b,a%b);
    int t=x;x=y;y=t-a/b*y;
    return tmp;//这里返回的是最大公因数
}    

5.递推的预处理gcd数组

很好理解的,能看懂:

for(int i=0;i<=T;i++)    pre[i][0]=pre[0][i]=i;
for(int i=1;i<=T;i++)//预处理gcd数组
    for(int j=1;j<=i;j++)
        pre[i][j]=pre[j][i]=pre[j][i%j];

6.拓欧的应用

下一篇讲,后面好多

posted @ 2020-04-25 17:50  初学者Ming  阅读(536)  评论(0编辑  收藏  举报