在寒假自己对自己的硬核知识进行了充电,这本书是学长极力推荐的,是专门给数学系的学生进行对数论进行全面认识和理解的入门书籍,虽然自己是计算机的,但是并不影响去阅读它,读的过程中就发现了,书中不少数学系的知识映入眼帘,我确实有点慌,有选择的进行了阅读。读的比较仓促,但是读完确实是有如神助,补齐了自己之前在学习acm数论的不少的坑,让自己对一些知识有了更深的认识。比如拓展欧几里得和欧拉函数。
-一。毕达哥拉斯定理(勾股定理)
a^2+b^2=c^2;(a,b的奇偶性是相反的,且c总是奇数)
有一个神奇的规律就是存在两个数字s,t,使得a=s*t, b=(s^2-t^2)/2, c=(s^2+t^2)/2;
这个比较有实用价值,是对从小就开始学习的勾股定理有了实际性的鼓励总结。
二。费马大定理
a^n+b^n=c^n。(当n>=3,方程式无解)
很显然当n==0时这个等式不成立的,所以范围就从整个整数域缩到了{0,1,2}, 又缩小到{1,2}。看是很鸡肋的定理,但是这个就是作为常识的存在在acm题目中。
三。欧几里得算法和拓展欧几里得算法
gcd(a,b)为a,b的最大公因子,LCM(a,b)为a,b的最小公倍数。
且二者存在关系LCM(a,b)*gcd(a,b)=a*b;
欧几里得算法实质上就是由直到余数为零的一系列带余除法组成的。
注意如何在每一步用A除以B得到商Q和余数R,A=B*Q+R,然后在下一步用数B与R代替原来的A与B,继续此过程直到得到余数R==0为止。
int gcd(int a,int b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
我经常更加形象化的理解,就是给我们一个长方形的纸条,问这个纸条中构成它的最大的基础正方形的边长是多少。(即由有限个基础正方形构成所提供的长方形,求解它的最大边长)。
首先咱们将这个长方形进行撕开,撕下最大的一个正方形,那么留下一个新的长方形,之后再次进行这个操作,直到再次撕完之后剩下的是个正方形为止。那么这个正方形就是该长方形的最大基础正方形,它的边长就是提供长方形的长宽的最大公因子。
ax+by的最小正整数值为gcd(a,b).
所以咱们去求解ax+by=gcd(a,b)
下边以22x+60y=gcd(22,60)为例,a=60,b=22;
60=2*22+16 | 16=a-2b
22=1*16+6 | 6=b-(a-2b)=3b-a
16=2*6+4 | 4=a-2b-2(3b-a)=3a-8b
4=2*2+0 | 2=3b-a-3a+8b=-4a+11b
over | 始终把握,最新余数=a的倍数*a+b的倍数*b
所以22*11-60*4=gcd(22,60)=2;
过程可以概述为左边等式是欧几里得算法,右边的等式是计算ax+by=gcd(a,b)的解
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 t=x;
x=y;
y=t-a/b*y;
return r;
}
解释:显然当b==0时,gcd(a,b)=a;此时x=1,y=0;
当ab<>0时,设ax1+by1=gcd(a,b)
bx2+(a mod b)y2=gcd(b,a mod b);
又因为gcd(a,b)=gcd(b,a mod b)
所以 a*x1+b*y1=b*x2+(a-a/b*b)y2=b*x2+a*y2-(a/b)*b*y2;
等式左右恒成立,x1=y2,y1=x2-(a/b)*y2;
注意使用exgcd求解的x,y是一组解,然后其通解为(x+kb,y-ka)
a*(x+kb)+b*(y-ka)=ax+kab+by-kab=ax+by;
拓展欧几里得的实际应用:
①求模的逆元
同余方程ax≡b(mod n) 若gcd(a,n)=1,则方程只有唯一的解。
在这种情况下,若b==1, 同余方程为ax≡1(mod n), gcd(a,n)=1,这时称求出的x为a的对模n的乘法逆元,实际就是求解方程ax+ny=1的x解。
②线性同余方程
ax≡b(mod n)
当b%(gcd(a,n))==0,则有解,且恰好有gcd(a,n)个解。 x=x0+k*n/g(k=0,1,.....g-1)
可转换为ax+ny=b.
③求解不定方程
ax+by=c
首先要保证c%(gcd(a,b))==0,则有解
设g=gcd(a,b)
a'=a/g b'=b/g cc'=c/g;
则a'x'+b'y'=1的解 可exgcd求解
a'c'x'+b'c'y'=c'可求
a'gc'x'+b'gc'y'=c'g
即ac'x'+bc'y'=c
所以x0=c'x' y0=c'y';
四。费马小定理
设p是素数,a是任意整数且a≠0(mod p)
则 a^(p-1)≡1(mod p)
用途可简化幂的取模运算
2^35(mod 7) =2^(6*5+5) (mod 7)= (2^6 (mod 7) )^5 * 2^5(mod 7)=1^5 * 2^5 (mod 7) =32 (mod 7) =4
是不是觉得这样简直好用到哭泣啊,但是如果p不是素数的时候应该怎么办呢,这个时候就提出了欧拉函数这个神奇的东西
五。欧拉函数
1.欧拉函数
Φ(m)= #{a: 1<=a<=m, gcd(a,m)=1 }. #是求解这个集合中的元素的数目的。
所以Φ(m)就是表示从1到m之间与m互素的整数的数目。
明显可知 ,若m是素数,Φ(m)=m-1。
欧拉函数的特殊:①如果p是素数,且k>=1,则Φ(p^k)=p^k-p^(k-1);
②如果gcd(m,n)=1,则Φ(mn)=Φ(m)*Φ(n);
③设p1,p2,p3......pr 都是整除m的不同素数,则Φ(m)=m*(1-1/p1)*(1-1/p2)....*(1-1/pr);
④如果p是素数,对于任意整数n,Φ(n*p)的值的求解
ⅰ 若n不可以整除p,Φ(n*p)=Φ(n)*Φ(p);
ⅱ 若n可以整除p,Φ(n*p)=Φ(n)*p;
2.欧拉公式
如果gcd(a,m)=1,则a^Φ(m)≡1(mod m)
int Eluer(int n)//求解某个数的欧拉函数
{
int ret=n;
for(int i=2;i<=sqrt(n);i++)
{
if(n%i==0)
{
ret=ret/i*(i-1);
while(n%i==0)
n/=i;
}
}
if(n>1)
ret=ret/n*(n-1);
return ret;
}
//求解1-n这个区间的所有数的欧拉函数值
const int maxn=1e5+100;
int prime[maxn];
int phi[maxn];
bool flag[maxn];
int num=0;
void eluer(int n)
{
phi[1]=1;
for(int i=2;i<=n;i++)
{
if(flag[i]==0)
{
prime[++num]=i;
phi[i]=i-1;
}
for(int j=1;j<=num&&prime[j]*i<=n;j++)
{
flag[prime[j]*i]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else
{
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
}
}
六。中国剩余定理(CRT)
设正整数m1,m2,.....mk两两互素,则存在同余方程组
x≡a1(mod m1)
x≡a2(mod m2)
x≡a3(mod m3)
.............
x≡ak(mod mk)
存在整数解x
咱们研究的就是怎样求出来在这个x。
明显可知,在模M=m1*m2*....*mk的情况下,x是唯一存在的,
x=(a1*M1*M1^-1 +a2*M2*M2^-1 +.....+ak*Mk*Mk^-1)(mod M)
其中Mi =M/mi ,而Mi^-1 为Mi 在M的逆元。
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 t=x;
x=y;
y=t-a/b*y;
return r;
}
int CRT(int a[],int m[],int n)
{
int M=1;
int ans=0;
for(int i=1;i<=n;i++)
M*=m[i];
for(int i=1;i<=n;i++)
{
int x,y;
int Mi=M/m[i];
exgcd(Mi,m[i],x,y);
ans=(ans+a[i]*Mi*x)%M;
}
if(ans<0)
ans+=M;
return ans;
}
int main()
{
int a[]={0,2,3,2};
int m[]={0,3,5,7};
printf("%d\n",CRT(a,m,3));
}
七。斐波那契兔子问题与线性递归序列
递推公式
F1=1,F2=1,Fn=Fn-1+Fn-2,n>=3;
比内公式
Fn=1/√5 { ((1+√5 )/2)^n-((1-√5 )/2)^n }
整理的思路有些零散,只是初次阅读的一些收获,记录一下(= =)!