[关闭]
@happyforever 2018-11-01T02:48:27.000000Z 字数 14449 阅读 1071

2018.6.7清北学堂学习笔记

清北学堂 数论

Day2


上午

数论

数论是纯粹数学的分支之一,主要研究证整数的性质
初等数论主要就是研究整数环的整除理论及同余理论。此外它也包括了连分数理论和少许不定方程的问题。本质上说,初等数论的研究手段局限在整除性质上。
初等数论中经典的结论包括算术基本定理、欧几里得的质数无限证明、中国剩余定理、欧拉定理(其特例是费马小定理)、高斯的二次互反律、商高定理、佩尔方程的连分数求解法等等。
应用:密码学,hash算法等。

某些著名猜想
哥德巴赫猜想:是否每个大于2的偶数都可写成两个质数之和?
孪生素数猜想:孪生素数就是差为2的素数对,例如11和13。是否存在无穷多的孪生素数
是否存在无穷多的梅森素数?
费马猜想(费马大定理)。
黎曼猜想

1.整除

  • 对于整数,如果且存在整数,使得,我们就称整除(或者整除),的约数,的倍数。(不同的书上定义略有不同)
  • 摘自《具体数学》(比值是一个整数)

这个性质奠定了整个数论的基础,所以赋予它一个特殊记号会更方便,记为
整除的性质:
自反性:
对称性:若,则
传递性:如果,那么
如果,那么
如果,且,那么
如果,且,那么
,如果,则
(m是非零整数)。
对任意两个整数都有


传递性证明:
因为,所以


对任意两个整数都有
证明:
左边推出右边:
,对于任意两个整数都有,相加得:,故
右边推出左边:
因为对任意两个整数都有
时,,故
时,,故


2.素数
定义:一个大于的正整数,除了和它自身外,不能被其他正整数整除的数叫做素数;否则称为合数。
素数有无限多个
证明(反证法):
假设有有限多个
那么记最大的素数,假定
那么一定没有约数,所以它也是一个素数,且,假设不成立
所以素数有无限多个

素数定理:
  • 很大时,小于的素数的个数近似等于

算数基本定理
  • 任何一个大于的正整数,都可以唯一分解成有限个素数的乘积。
  • 也可以写成

3.素数判定
给一个正整数 ,如何判定它是否为素数?

试除法!
解法0:枚举从 的所有正整数,检查整除性,时间复杂度


解法1:枚举从 的所有正整数,检查整除性,时间复杂度
假设一个数能整除,即,那么也必定能整除,不妨设(否则可令),则有,即


如果 是合数,那么它必然有一个小于等于的素因子。
解法2:枚举从 的所有素因子,检查整除性,单次时间复杂度


解法3:Miller-Rabin素性测试。


质因数分解
利用性质:如果 是合数,那么它必然有一个小于等于的素因子
枚举试除,对于一个因子不断除直到除净
最后可能会留有一个大的素因子。


4.因子
朴素的求因子的方法为枚举的数进行整除判定,复杂度为
加入一个优化,如果的因子,那么必然也为的因子,不妨设,则有,所以只要从枚举即可
注意特判(不要重复计算),复杂度

  1. for(int i=1;i*i<=n;++i)
  2. if(n%i==0)
  3. {
  4. d[++dsz]=i;
  5. if(i*i<n)d[++dsz]=n/i;
  6. }


由乘法计数原理得,约数个数为


5.筛素数
给一个正整数 ,求出不超过 的所有素数。

埃拉托斯特尼筛法
逐次枚举 ,设当前枚举到 ,如果没有被标记过,那么是素数,并将的倍数标记为“非素数”。

  1. 朴素版写法
  2. bool not_prime[];
  3. not_prime[1]=true;
  4. for(int i=2;i<=n;++i)
  5. for(int j=i+i;j<=n;j+=i)
  6. not_prime[j]=true;

复杂度为
根据调和级数,大概是

  1. bool not_prime[];
  2. not_prime[1]=true;
  3. for(int i=2;i<=n;++i)
  4. if(!not_prime[i])
  5. for(int j=i+i;j<=n;j+=i)
  6. not_prime[j]=true;

复杂度


线性筛
逐次枚举 ,并且记录下当前找到的所有素数。
然后每处理到一个数,从小到大枚举所有当前找到的素数,将其与的乘积剔除。直到被当前枚举的素数整除为止。

  1. bool not_prime[];
  2. int prime[],psz;
  3. not_prime[1]=true;
  4. for(int i=2;i<=n;++i)
  5. if(!not_prime[i])prime[++psz]=i;
  6. for(int j=1;j<=psz;++j)
  7. {
  8. if(i*prime[j]>n)break;
  9. not_prime[i*prime[j]]=true;
  10. if(i%prime[j]==0)break;
  11. }

第10行那句话是保证线性复杂度的关键
例:
30
6*5筛掉一次
10*3筛掉一次
15*2筛掉一次
会被重复筛除
加上这句话之后
30只会被15*2筛掉
可以保证每个数都被它最小的质因子筛除了,故算法复杂度

例题:
给定个数,范围为,判定它们是素数还是合数。

解:
首先1不是素数,如果,则枚举范围内的素数进行试除
范围内的素数可以通过筛法预先筛出来。


区间筛
题目:给定l,r,求[l,r]范围内的素数
解法:枚举
范围内的素数可以通过筛法预先筛出来

  1. //前面有个线性筛
  2. for(int i=1;i<=psz;++i)
  3. {
  4. int p=prime[i];
  5. for(int j=(l-1)/p+1;j<=r/p;++j)
  6. not_prime[j*p-l]=true;//-l是因为l和r的取值太大,但是l~r比较小
  7. }

复杂度
也可以枚举[m,n]上面每个数,用Miller-Rabin算法判定,但是没有充分利用题目性质


6.mod运算
定义来自于带余除法

除法定理
  • 如果是两个整数,,存在唯一一对整数,满足

对任意整数和任意整数,称为除法的,值为除法的余数[1]
也就是
这就将mod定义成为一个二元运算,该定义当是实数时也有意义,不过在数论中我们通常只对整数用此定义。
是负数时,计算机语言用的是另一种定义。


最大公约数
定义:

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

对于计算,欧几里得算法用到递归式

求证:对任意非负整数和正整数
证明:
只需要证明上面两者能相互整除。
所以
由带余除法可以得出:,其中
所以是a和b的一个线性组合,所以
又因为
所以,即

证明和上述过程几乎一样。


裴蜀定理

对任何和它们的最大公约数,关于未知数的线性不定方程(称为裴蜀等式):有整数解当且仅当,可知有无穷多解。特别地,一定存在整数,使成立。

引理的证明:
的线性组合集中最小的正元素,对于某个,有
,则有

因此也是的一个线性组合
由于是这个线性集合中的最小正整数,又,可得
因此有,同理有,因此的公约数,所以有
其实用exgcd就能得出存在等于的线性组合。
证毕

裴蜀定理可以从二元拓展到多元

素数的推论4这条性质可以推广到一般情形,若,则存在使得


7.素数、算数基本定理

任何一个大于的正整数数,都可以唯一分解成有限个素数的乘积


也称唯一分解定理

存在性证明:
如果不是素数,那么他就有一个因子,使得,这样我们就能写成,同时(根据归纳法)我们知道可以写成素数的乘积

唯一性证明:
反证法
假设有两种方法分解,
用刚刚得出的引理:若,则存在使得。因为所以存在使得,又因为也是质数,所以,同时除掉之后由归纳法即可得证

由算数基本定理
两个数相乘就等价于指数表示相加。
,对所有
这就蕴含
,对所有
由此可以立即推出
,对所有
,对所有

由此还可得一个小结论

例题:hdu4497 GCD and LCM
三个未知数,它们的gcd为,lcm为已知,求三元组的个数
解法:
对于每个素因子单独处理
假设素因子为分解式中的指数为分解式中的指数为,那么显然时不可能存在满足条件的三元组,所以只需要讨论的情况,对于单个因子,问题转化成了求三个数,满足,这是一个排列组合问题,三元组的种类数当时只有1中,否则答案就是
最后根据乘法原理将每个素因子对应的种类数相乘即为最后的答案了


8.扩展欧几里得
求解不定方程(假设)
时有,此时
不为时,根据GCD递归定理
可得

移项得
所以
是不定方程 的一组解, ,那么全部解为,其中 为所有整数

  1. int exgcd(int a,int b,int &x,int &y)
  2. {
  3. if(!b)
  4. {
  5. x=1,y=0;
  6. return a;
  7. }
  8. int d=exgcd(b,a%b,y,x);
  9. y-=a/b*x;
  10. return d;
  11. }

例题:
2012NOIP同余方程
已知,且a,b互质,求x
做法:转化为,代进exgcd直接求即可,y没用,x即为答案

poj1061青蛙的约会
两只青蛙同向跳跃,A的出发点是x,B的出发点是y,它们在一个首尾相接的数轴上
A一次跳m米,B一次跳n米,数轴总长度为l
问它们至少跳了几次之后可以相遇
解:
求解a:


它就等于

把模去掉,就等于

然后,用exgcd求

NOI2002荒岛野人
一个岛是环状的,环上排列有 个洞穴,顺时针编号为1到 ,有 (不超过 ) 个野人,第 个野人一开始住在洞穴 中,每一年要顺时针迁移 个洞穴,走 年后就会死去。求满足在野人有生之年都不存在两个野人同住一个洞穴的情况下,最少的洞穴总数。保证 不超过

解法:
答案不满足单调性,不能二分。我们只能从小到大枚举洞穴数,检查其是否能满足条件,和上一题类似


9.mod:同余关系
若两个整数除以正整数有相同的余数,那么称对于模同余,用式子表示为:

在不产生歧义的情况下,可以省略
我们可以用另一种方式来解读同余式:是整数,即
同余是一个等价关系,它满足自反律,对称律,传递律,这些都很容易证明。
此外,它还满足可加减性:若,那么。 可乘性:若,那么
我们对方程所习惯做的大多数运算对同余式都可以运用。但要注意,除法运算是有条件的

10.逆元
*定义:
设正整数模 ,对于任意正整数 满足 ,存在 满足
,称 为模 意义下 的逆元。%且

求逆元只需要用扩展欧几里得解一个线性同余方程即可,还可以用费马小定理或欧拉定理来求。
有逆元的充要条件是(方程有解)

O(n)预处理求逆元1~n的逆元

  1. q[1]=1;
  2. for(int i=2;i<=n;++i)
  3. q[i]=q[i-1]*i%mod;
  4. p[n]=ksm(q[n],mod-2);
  5. for(int i=n;i>1;--i)
  6. p[i-1]=p[i]*i%mod;

另一种解法:





11.剩余系、完全剩余系和简单剩余系


下午

12.费马小定理
是一个素数, 是一个整数且不是 的倍数,那么


注意到若有 ,那么有
所以构成模的一个完全剩余系。
由完全剩余系的性质,


,故


13.素性测试
很遗憾,费马小定理的逆定理是不成立的。
,满足 的非素数 是存在的,比如

对于整数 ,称满足 的合数为以 为底的 伪素数

经测试,前 10 亿的自然数中,同时以 2 和 3 为底的伪素数有 1272 个。
我们用费马小定理验证素数的话,出错的概率大概只有 0.000025。可以制作一张伪素数表

如果我们随机选取若干个小于待测整数的正整数作为底 ,然后用费马小定理来测试,存在无穷多个被称为Carmichael数的整数:对于任意与其互素的整数算法的计算结果都是1
最小的五个Carmichael数是561、1105、1729、2465和2801。


MillerRabin素性测试

费马小定理的逆命题不成立,所以只能使用逆否命题
二次探测定理





是素数,是一个正整数,且 ,那么
,由 是素数易证。
设待测数为 ,取一个比 小的正整数 ,设 ,若 是素数,则要么,要么存在一个 ,满足
随机选取 个小于待测整数 的正整数作为底 ,用上面的结论来测试
时间复杂度

  1. #include <ctime>
  2. #include <cstdio>
  3. #include <algorithm>
  4. typedef long long ll;
  5. const int C=240,Time=10;
  6. ll ans;
  7. int T;
  8. ll mult(ll x,ll y,ll mod)
  9. {
  10. ll ret=0;
  11. for(;y;y>>=1,x=(x+x)%mod)
  12. if(y&1)
  13. ret=(ret+x)%mod;
  14. return ret;
  15. }
  16. ll ksm(ll x,ll y,ll mod)
  17. {
  18. ll ret=1;x%=mod;
  19. for(;y;y>>=1,x=x*x%mod)
  20. if(y&1)
  21. ret=ret*x%mod;
  22. return ret;
  23. }
  24. ll gcd(ll a,ll b)
  25. {
  26. if(!a)return 1;
  27. if(a<0)return gcd(-a,b);
  28. return b?gcd(b,a%b):a;
  29. }
  30. bool Witness(ll a,ll n)
  31. {//二次探测定理
  32. ll t=0,u=n-1;
  33. while(!(u&1))++t,u>>=1;
  34. ll x0=ksm(a,u,n);
  35. if(x0==1)return 0;
  36. for(int i=0;i<t;++i)
  37. {
  38. if(x0==n-1)return 0;
  39. x0=mult(x0,y0,n);
  40. }
  41. return 1;
  42. }
  43. bool Miller_Rabin(ll n,ll t)
  44. {
  45. if(n==2)return 1;
  46. if(!(n&1))return 0;
  47. srand(time(0));
  48. for(int i=0;i<t;++i)
  49. {
  50. ll a=rand()%(n-1)+1;
  51. if(Witness(a,n))return 0;
  52. }
  53. return 1;
  54. }
  55. /*//后面的内容是Pollard_Rho分解大数质因子
  56. ll Pollard_Rho(ll n,ll c)
  57. {
  58. ll x=rand()%n,y=x,k=2;
  59. for(int i=2;;++i)
  60. {
  61. x=(mult(x,x,n)+c)%n;
  62. ll d=gcd(y-x,n);
  63. if(d!=-1&&d!=n)return d;
  64. if(x==y)return n;
  65. if(i==k)y=k,k<<=1;
  66. }
  67. }
  68. void get_small(ll n,ll c)
  69. {
  70. if(n==1)return ;
  71. if(Miller_Rabin(n,Time))
  72. {
  73. ans=min(n,ans);
  74. return ;
  75. }
  76. ll p=n;
  77. while(p>=n)p=Pollard_Rho(p,c--);
  78. get_small(p,c);
  79. get_small(n/p,c);
  80. }
  81. */
  82. int main()
  83. {
  84. srand(time(0));
  85. scanf("%d",&T);//多组数据
  86. while(T--)
  87. {
  88. ll n;
  89. scanf("%lld",&n);
  90. if(Miller_Rabin(n,Time))
  91. printf("Maybe a prime\n");
  92. else
  93. {
  94. printf("Not a prime\n");
  95. /*
  96. ans=n,getsmall(n,C);
  97. printf("%lld",ans);
  98. */
  99. }
  100. }
  101. return 0;
  102. }
  103. */

中国剩余定理
在《孙子算经》中有这样一个问题:有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问物几何?
《孙子歌诀》:三人同行七十稀,五树梅花廿一支,七子团圆正半月,除百零五便得知。
例:求解一元线性同余方程组:


两两互素的时候,是经典的中国剩余定理,百度百科有详细的介绍

它等价于

两个方程联立

根据裴蜀定理,我们可以知道如果,那么这个方程就有整数解,否则它就不存在整数解


对于


其中g为gcd(m1,m2)
往回代入可得

这个解实际上等价于下面这个同余方程

例题:


其中

这是个非常经典的问题
其非常经典的思路:
取余,一共约有个结果
对于,种结果
对于的范围是,至多有种结果

其非常经典的写法:

  1. for(int i=1,j;i<=n;i=j+1)
  2. {
  3. j=n/(n/i);
  4. ans+=(j-i+1)*(n/i);
  5. }

例题2:余数之和
输入,计算的结果

解法:
和上一个问题类似,商至多有
又注意到对于商相同,余数是一个等差数列
如果除数的范围是[l,r],商为k,那么对答案的贡献是

例题3:模积和
输入n,m,计算

解法:
如果没有这个条件,那么后面可以用分配率拆成两部分,然后乘起来
是很容易在的时间内计算的
现在要求,那么容易想到先算出全部,然后减去的部分
再考虑对于结果都相同的一组,有什么相纸
容易发现后面两个均为等差数列,用分配率和前n个自然数和,平方和的公式就可以在的时间内计算了。
总时间复杂度

具体化简过程:


14.数论函数

数论函数是定义在整数集合商的函数
一些常见的数论函数:
* ,表示正整数n的正因子之和
* ,表示正整数n的正因子个数
* 表示[1,n]中与n互素的整数个数,称作欧拉函数

数论函数f叫做是积性函数
对于gcd(n,m)==1,若f(n*m)=f(n)*f(m)那么称函数f为积性函数
若对于任意n,m都有f(n*m)=f(n)*f(m),那么称函数f为完全积性函数


欧拉函数
考虑如何计算

是积性函数,但不是完全积性函数
一个有趣的推论:
考虑分母为n的真分数,和他们化成最简分数,可以说明这个结论

欧拉定理
  • 设n为正整数,a是与n互素的整数,则

欧拉定理的证明与费马小定理类似

线性欧拉筛

  1. bool not_prime[];
  2. int prime[],psz;
  3. not_prime[1]=true;
  4. phi[1]=1;
  5. for(int i=2;i<=n;++i)
  6. if(!not_prime[i])
  7. {
  8. prime[++psz]=i;
  9. phi[i]=i-1;
  10. }
  11. for(int k,j=1;j<=psz;++j)
  12. {
  13. k=i*prime[j];
  14. if(k>n)break;
  15. not_prime[i*prime[j]]=true;
  16. if(i%prime[j]==0)
  17. phi[k]=prime[j]*phi[i];
  18. else phi[k]=phi[i]*(prime[j]-1);
  19. }

莫比乌斯函数
如下定义莫比乌斯函数

线性莫比乌斯函数筛

  1. bool not_prime[];
  2. int prime[],psz;
  3. not_prime[1]=true;
  4. phi[1]=mu[1]=1;
  5. for(int i=2;i<=n;++i)
  6. {
  7. if(!not_prime[i])
  8. {
  9. prime[++psz]=i;
  10. phi[i]=i-1;
  11. mu[i]=-1;
  12. }
  13. for(int k,j=1;j<=psz;++j)
  14. {
  15. k=i*prime[j];
  16. if(k>n)break;
  17. not_prime[k]=true;
  18. if(i%prime[j]==0)
  19. mu[k]=0;
  20. else mu[k]=-mu[i];
  21. }
  22. }


其中表示:当时值为1,否则为0
那么时显然
,设
显然d的每个质因子的指数为1才有贡献,否则,这样的d有C_m^r个
所以

已知有二项式定理(看百度百科好像是杨辉三角),则


莫比乌斯反演
有两种写法
1.


2.

对于第一个写法的证明:

例题链接

T1
的对数
解法
求phi的前缀和
T2
是质数,的对数
SDOI2008仪仗队

前两题数据范围5w

T3
的个数
解法
的组数


T4
的个数,多组数据
解法


由考虑到多组数据,使用整除分块



数据组数和数据范围都是5w

T5
的个数,多组数据


[1] (二元运算)基本公式
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注