数论(未完成)

一、质数

1.定义:若一个正整数无法被除了1和它自身之外的任何自然数整除,则称该数为质数(或素数),否则称该正整数为合数。

在整个自然数集合中,质数的数量不多,分布比较稀疏,对于一个足够大的整数N,不超过N的质数大约有N/lnN个,即每lnN个数中大约有1个质数。

2.质数的判定:试除法

若一个正整数N为合数,则存在一个能整除N的数T,其中2<=T<=sqrt(n)。
证明:
由定义得,因为N是合数,所以存在一个能整除N的数M,其中2<=M<=N-1。

反证法。假设命题不成立,那么这样的数M一定满足sqrt(n)+1<=M<=N-1.
因为M能整除N,所以它们的商N/M也能整除N。而2<=N/M<=sqrt(n),令T=N/M,这与假设矛盾。
故假设不成立,原命题成立。
证毕。

根据上述命题,我们只需要扫描2~sqrt(n)之间的所有整数,依次检查它们能否整除N,若都不能整除,则N是质数,否则N是合数。
复杂度O(sqrt(n))。

1 bool judge(int n){
2     for(int i=2;i<=sqrt(n);i++){
3         if(n%i==0) return 0;
4     }
5     return 1;
6 }
View Code

其他高效率随机算法:Miller-Robbin

3.质数的筛选

(1)Eratosthenes筛法

Eratosthenes筛法基于这样的想法:任意整数x的倍数2x,3x,…都不是质数。根据质数的定义,上述命题显然成立。

我们可以从2开始,由小到大扫描每个数x,把它的倍数2x,3x,…,[N/x]·x标记为合数。

当扫描到一个数时,若它尚未被标记,则它不能被2~x-1之间的任何数整除,该数就是质数。

1 void Eratosthenes(int n){
2     memset(v,0,sizeof(v));
3     for(int i=2;i<=n;i++){
4         if(v[i]) continue ;
5         cout<<i<<' ';
6         for(int j=1;j<=n/i;j++) v[i*j]=1;
7     }
8 }
View Code

实际上,小于x^2的x的倍数在扫描更小的数时就已经被标记过了。

因此,我们可以对Eratosthenes筛法进行优化,对于每个数x,我们只需要从x^2开始,把x^2,(x+1)*x,[N/x]·x标记为合数即可。

Eratosthenes筛法的时间复杂度为O(NloglogN)。

(2)线性筛法

我们在生成一个需要标记的合数时,每次只向现有的数中乘上一个质因子,并且让它是这个合数的最小质因子。

具体地说,我们采用如下的线性筛法,其中v数组记录每个数的最小质因子。每个合数只会被它的最小质因子筛一次,时间复杂度为O(N)。

 1 int v[N],prime[N],cnt;
 2 void primes(int n){
 3     memset(v,0,sizeof(v));
 4     cnt=0;
 5     for(int i=2;i<=n;i++){
 6         if(!v[i]){
 7             v[i]=i,prime[++cnt]=i;
 8         }
 9         for(int j=1;j<=m;j++){
10             if(prime[j]>v[i]||prime[j]>n/i) break ;
11             v[i*prime[j]]=prime[j];
12         }
13     }
14     for(int i=1;i<=cnt;i++){
15         cout<<prime[i]<<' ';
16     }
17 }
View Code

4.质因数分解

(1)算术基本定理

任何一个大于1的正整数都能唯一分解为有限个质数的乘积,可写作:

N=p1^c1*p2^c2…pm^cm

其中ci都是正整数,pi都是质数,且满足p1<p2<…<pm

(2)试除法

结合质数判定的“试除法”和质数筛选的“Eratosthenes筛法”,我们可以扫描2~sqrt(n)的每个数d,若d能整除N,则从N中除掉所有的因子d,同时累计除去的d的个数。

因为一个合数的因子一定在扫描到这个合数之前就从N中被除掉了,所以在上述过程中能整除N的一定是质数。

最终就得到了质因数分解的结果,易知时间复杂度为O(sqrt(n))。

特别地,若N没有被任何2~sqrt(n)的数整除,则N是质数,无需分解。

 1 void divide(int n){
 2     cnt=0;
 3     for(int i=2;i<=sqrt(n);i++){
 4         if(n%i==0){
 5             prime[++cnt]=i,c[cnt]=0;
 6             while(n%i==0) n/=i,c[cnt]++;
 7         }
 8     }
 9     if(n>1){
10         prime[++cnt]=n,c[cnt]=1;
11     }
12     for(int i=1;i<=cnt;i++){
13         cout<<prine[cnt]<<'^'<<c[i]<<endl;
14     }
15 }
View Code

进阶:“Pollard's Rho”算法

二、约数

1.定义:若整数n除以整数d的余数为0,即d能整除n,则称d是n的约数,n是d的倍数,记为d|n。

2.算术基本定理的推论

在算术基本定理中,若正整数N被唯一分解为N=p1^c1*p2^c2...pm^cm,其中ci都是正整数,pi都是质数,且满足p1<p2p3<p4...<pm,则N的正约数集合可写作:
{p1^b1 p2^b2...pm^bm},其中0<=bi<=ci
N的正约数的个数为:(c1+1)*(c2+1)*(cm+1)
N的所有正约数的和为:(1+p1^1+p1^2+...p1^c1)*...*(1+pm^1+pm^2+...pm^cm)

3.求N的正约数集合:试除法

若d>=sqrt(n)是N的约数,则N/d<=sqrt(n)也是N的约数。约数总是成对出现。
因此,只需要扫描d=1~sqrt(n),尝试d能否整除N,若能整除,则N/d也是N的约数。时间复杂度为O(sqrt(n))

 1 int factor[N],cnt;
 2 for(int i=1;i*i<=n;i++){
 3     if(n%i==0){
 4         factor[++cnt]=i;
 5         if(i!=n/i) factor[++cnt]=n/i; 
 6     }
 7 } 
 8 for(int i=1;i<=cnt;i++){
 9     cout<<factor[i]<<' ';
10 }
View Code

试除法的推论:一个整数N的约数上界为2*sqrt(n)。

4.求1~N每个数的正约数集合:倍数法

若用“试除法”分别求出1~N每个数的正约数集合,时间复杂度过高,为O(N*sqrt(n))。
可以反过来考虑,对于每个数d,1~N中以d为约数的数就是d的倍数d,2d,3d,….[N/d]*d。
以下程序采用“倍数法”求出1~N每个数的正约数集合;

 1 vector<int>factor[N];
 2 for(int i=1;i<=n;i++){
 3     for(int j=1;j<=n/i;j++){
 4         factor[i*j].push_back(i); 
 5     }
 6 }
 7 for(int i=1;i<=n;i++){
 8     for(int j=0;j<factor[i].size();j++){
 9         cout<<factor[i][j]<<' ';
10     }
11     puts("");
12 }
View Code

上述算法的时间复杂度为O(N+N/2+N/3+…+N/N)=O(NlogN)。

倍数法的推论:1~N每个数的约数个数的总和大约为NlogN。

5.最大公约数

gcd(a,b)=gcd(b,a)
gcd(a,b)=gcd(-a,b)
gcd(a,b)=gcd(|a|,|b|)
gcd(a,0)=|a|
gcd(a,k*a)=|a|
gcd(a*n,b*n)=n*gcd(a,b)
若d|a且d|b,则d|gcd(a,b)
若n|ab且gcd(a,n)=1,则n|b
若gcd(a,p)=1且gcd(b,p)=1,则gcd(a*b,p)=1

(1)定义:

若自然数d同时是自然数a和b的约数,则称d是a和b的公约数。在所有a和b的公约数中最大的一个,称为a和b的最大公约数,记为gcd(a,b)。

若自然数m同时是自然数a和b的倍数,则称m是a和b的公倍数。在所有a和b的公倍数中最小的一个,称为a和b的最小公倍数,记为lcm(a,b)。

同理,我们也可以定义三个数以及更多个数的最大公约数、最小公倍数。

(2)定理:任意a,b属于N+,gcd(a,b)*lcm(a,b)=a*b。

证明:
设d=gcd(a,b),a0=a/d,b0=b/d。根据最大公约数的定义,有gcd(a0,b0)=1。
再根据最小公倍数的定义,有lcm(a0,b0)=a0*b0,于是lcm(a,b)=lcm(a0*d,b0*d)=lcm(a0,b0)*d=a0*b0*d=a*b/d。

证毕。

(3)九章算术-更相减损术:

任意a,b属于N+,a>=b,有gcd(a,b)=gcd(b,a-b)=gcd(a,a-b)。

任意a,b属于N+,有gcd(2a,2b)=2gcd(a,b)。

证明:根据最大公约数的定义,后者显然成立,我们主要证明前者。

对于a,b的任意公约数d,因为d|a,d|b,所以d|(a-b)。因此d也是b,a-b的公约数,反之亦成立。
故a,b的公约数集合与b,a-b的公约数集合相同。于是它们的最大公约数自然也相等,对于a,a-b同理。
证毕。

(4)欧几里得算法:

证明:

若a<b,则gcd(b,a mod b)=gcd(b,a)=gcd(a,b),命题成立。

若a>b,不妨设a=q*b+r,其中0<=r<b。显然r=a mod b。
对于a,b的任意公约数d,因为d|a,d|q*b,故d|(a-q*b),即d|r,因此d也是b,r的公约数。反之亦成立。
故a,b的公约数集合与b,a modb的公约数集合相同。于是它们的最大公约数自然也相等。

证毕。

1 int gcd(int a,int b){
2     return b?gcd(b,a%b):a; 
3 } 
View Code

使用欧几里得算法求最大公约数的复杂度为0(log(a+b))。

(5)类欧几里得算法:

6.互质与欧拉函数

(1)定义:

任意a,b属于N+,若gcd(a,b)=1,则称a,b互质。

对于三个数或更多个数的情况,我们把gcd(a,b,c)=1的情况称为a,b,c互质;
把gcd(a,b)=gcd(a,c)=gcd(b,c)=1称为a,b,c两两互质。后者显然是一个更强的条件。

(2)欧拉函数:1~N中与N互质的数的个数被称为欧拉函数,记为φ(N)。

若在算术基本定理中,N=p1^c1*p2^c2...pm^cm,则:

φ(N)=N*(p1-1)/p1*(p2-1)/p2*...*(pm-1)/pm=N*Π(1-1/p)

证明:
设p是N的质因子,1~N中p的倍数有p,2p,3p…,(N/p)*p,共N/p个。

同理,若q也是N的质因子,则1~N中q的倍数有N/q个。如果我们把这N/p+N/q个数去掉,那么p*q的倍数被排除了两次,需要加回来一次。
因此,1~N中不与N含有共同质因子p或q的数的个数为:

N-N/p-N/q+N/(p*q)=N*(1-1/p-1/q+1/(p*q))=N*(1-1/p)*(1-1/q)

类似地,可以在N的全部质因子上使用容斥原理,即可得到1~N中不与N含有任何共同质因子的数的个数,也就是与N互质的数的个数。

证毕。

根据欧拉函数的计算式,我们只需要分解质因数,即可顺便求出欧拉函数。

 1 int phi(int n){
 2     int ans=n;
 3     for(int i=1;i<=sqrt(n);i++){
 4         if(n%i==0){
 5             ans=ans/i*(i-1);
 6             while(n%i==0) n/=i; 
 7         }
 8     }
 9     if(n>1) ans=ans/n*(n-1);
10     return ans;
11 } 
View Code

(3)性质:

a.任意N>1,1~N中与N互质的数的和为N*φ(N)/2

b.若a,b互质,则φ(a*b)=φ(a)*φ(b)

证明:

因为gcd(n,x)=gcd(n,n-x),所以与n不互质的数x,n-x成对出现,平均值为n/2。因此,与n互质的数的平均值也是n/2,进而得到性质1。

根据欧拉函数的计算式,对a,b分解质因数,直接可得性质2。把性质2推广到一般的函数上,可以得到“积性函数”的概念。

证毕。

积性函数:如果当a,b互质时,有f(ab)=f(a)*f(b),那么称函数f为积性函数。

c.若f为积性函数,且在算术基本定理中N=Πpi^ci,则f(N)=Πf(pi^ci)

d. 若 p|n且p^2|n,则φ(n)=φ(n/p)*p

e.若p|n但p^2|n==false,则φ(n)=φ(n/p)*(p-1)

f.Σd|n φ(d)=n

证明:
把n分解质因数,按照积性函数的定义,性质3显然成立。

若p|n且p^2|n,则n,n/p包含相同的质因子,只是p的指数不同。直接把φ(n)与φ(n/p)按照欧拉函数的计算公式写出,二者相除,商为p,所以性质4成立。

若p|n但p^2|n==false,则n,n/p互质,由φ是积性函数得φ(n)=φ(n/p)*φ(p),而φ(p)=p-1,所以性质5成立。

设f(n)=Σd|n φ(d)。用乘法分配律展开比较,再利用φ是积性函数,得到:若nm互质,则f(nm)=Σd|nmφ(d)=(Σd|nφ(d))*(Σd|mφ(d))=f(n)*f(m).即Σd|nφ(d)是积性函数。对于单个质因子,f(p^m)=Σd|p^mφ(d)=φ(1)+φ(p)+φ(p^2)+…+φ(p^m)是一个等比数列求和再加1,结果为p^m。所以f(n)=Π(i=1 to m)f(pi^ci)=Π(i=1 to m)pi^ci=n,性质6成立。

证毕。

三、同余

1.定义:若整数a和整数b除以正整数m的余数相等,则称a,b模m同余,记为a同余于b(mod m)。

2.同余类与剩余系:

对于任意a属于[0,m-1],集合{a+km}的所有余数模m同余,余数都是a。该集合称为一个模m的同余类。
模m的同余类共有m-1个,它们构成m的完全剩余系。
1~m中与m互质的数代表的同余类共有φ(m)个,它们构成m的简化剩余系。
简化剩余系关于模m乘法封闭,这是因为若a,b(1<=a,b<=m)与m互质,则a*b也不可能与m有相同的质因子,即a*b也与m互质。
再由余数的定义即可得到a*b mod m 也与m互质,即a*b mod m也属于m的简化剩余系 

3.费马小定理:若p是质数,则对于任意整数a,a^p=a (mod p)

4.欧拉定理:

5.欧拉定理的推论:

6.扩展欧几里得算法:

Bezout定理:对于任意整数a,b,存在一对整数x,y,满足ax+by=gcd(a,b)

证明:

(1)Bezout定理:

(2)扩展欧几里得算法:

(3)乘法逆元:

7.线性同余方程:

(1)中国剩余定理:

8.高次同余方程:

(1)baby step giant step算法:

9.威尔逊定理:

10.离散对数:

11.阶与原根:

12.二次剩余:

四、矩阵乘法:

五、高斯消元与线性空间:

1.高斯消元:

2.异或高斯消元:

3.线性基:

4.线性空间:

5.行列式:

6.逆矩阵:

7.线性变换:

8.矩阵对角化:

9.分块矩阵乘法:

(1)matrix-tree定理:

六、组合计数

1.加法原理:

2.乘法原理:

3.排列数:

(1)多重集的排列数:

4.组合数:

(1)性质:

(2)组合数求法:

(3)二项式定理:

(4)多重集的组合数:

5.Lucas定理:

6.Catalan数列:

(1)证明:

(2)推论:

七、容斥原理与mobius函数

1.容斥原理:

2.多重集的组合数:

(1)证明:

3.mobius函数:

八、概率与数学期望

1.性质:

九、0/1分数规划:

十、博弈论之SG函数:

1.NIM博弈:

2.公平组合游戏IGG:

3.有向图游戏:

4.Mex运算:

5.SG函数:

6.有向图游戏的和:

(1)定理:

转载于:https://www.cnblogs.com/Moxingtianxia/p/11329894.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值