素数

一、定义

       素数又称质数,是指一个大于1的正整数,除了1和它本身外,没有其他约数的自然数,否则称为合数(规定1既不是质数也不是合数)。

二、性质

       质数的个数是无穷的。欧几里得的《几何原本》中有一个经典的证明。它使用了证明常用的方法:反证法。具体证明如下:假设质数只有有限的n个,从小到大依次排列为p1,p2,……,pn,设N=p1×p2×……×pn,那么,N+1是素数或者不是素数。

       如果
N+1
为素数,则
N+1
要大于p1,p2,……,pn,所以它不在那些假设的素数集合中。
      1、如果为合数,因为任何一个合数都可以分解为几个素数的积;而N和N+1的最大公约数是1,所以不可能被p1,p2,……,pn整除,所以该合数分解得到的素因数肯定不在假设的素数集合中。因此无论该数是素数还是合数,都意味着在假设的有限个素数之外还存在着其他素数。所以原先的假设不成立。也就是说,素数有无穷多个。
      2、其他数学家给出了一些不同的证明。欧拉利用黎曼函数证明了全部素数的倒数之和是发散的,恩斯特·库默的证明更为简洁,哈里·弗斯滕伯格则用拓扑学加以证明。
       例题:预先给定几个素数,则有比他们更多的素数。
       证明:
              设a,b,c是给定的素数,构造一个新的数t=a*b*c+1,则已有的素数a,b,c均不能整除t,所以要么t本身就是素数,此时t不等于a,b,c中任意一个数;要么t能被不同于a,b,c的某一个素数整除,因此必然存在一个素数p不同于已有的素数a,b,c。例如:2*3*5+1=31,3*5*7+1=106=2*53。也就是说,有了n个素数,就可以构造出第n+1个素数,因此素数有无穷多个。
三、数目计算
      尽管整个素数是无穷的,仍然有人会问“100,000以下有多少个素数?”,“一个随机的100位数多大可能是素数?”。素数定理可以回答此问题。
      1、在一个大于1的数a和它的2倍之间(即区间(a, 2a]中)必存在至少一个素数。
      2、存在任意长度的素数等差数列。 [1]
      3、一个偶数可以写成两个合数之和,其中每一个合数都最多只有9个质因数。(挪威数学家布朗,1920年)
      4、一个偶数必定可以写成一个质数加上一个合成数,其中合数的因子个数有上界。(瑞尼,1948年)
      5、一个偶数必定可以写成一个质数加上一个最多由5个因子所组成的合成数。后来,有人简称这结果为 (1 + 5)(中国潘承洞,1968年)
      6、一个充分大偶数必定可以写成一个素数加上一个最多由2个质因子所组成的合成数。简称为 (1 + 2) [2]
四、性质     
      质数具有许多独特的性质:
     (1)质数p的约数只有两个:1和p。
     (2)初等数学基本定理:任一大于1的自然数,要么本身是质数,要么可以分解为几个质数之积,且这种分解是唯一的。
     (3)质数的个数是无限的。
     (4)质数的个数公式
π(n)
是不减函数。
     (5)若n为正整数,在
n2
(n+1)2
之间至少有一个质数。
     (6)若n为大于或等于2的正整数,在n到
n!之间至少有一个质数。
     (7)若质数p为不超过n(
n≥40)的最大质数,则\frac{n}{2}"> 。
     (8)所有大于10的质数中,个位数只有1,3,7,9。 [2]
五、素数的相关定理    
       1. 唯一分解定理
        若整数a≥2,那么a一定可以表示为若干个素数的乘积(唯一的形式),即:
        a=p1*p2*p3*......*ps(其中pj为素数,成为a的质因子,1≤j≤s)
             如:1260=2*2*3*3*5*7=22*32*5*7
        2.威尔逊定理
        若p为素数,则(p-1)!≡-1(mod p)(其中n!表示n阶乘)
        威尔逊定理的逆定理也成立,即:
        若对某一正整数p,有(p-1)!≡-1(mod p),则p一定为素数。
        既然如此,则(p-1)!+1一定是p的倍数,所以再利用sin函数的特点,就可以构造出一个素数分布的函数曲线f(n):f(n)=sin(π*((n-1)!+1)/n)。这个函数值为0的点都是素数所在的点。
        3.费马定理
        若p为素数,a为正整数,且a和p互质,则:ap-1≡1(mod p)。
        证明:
        首先,p-1个整数a,2a,3a,...(p-1)a中没有一个是p的倍数。
        其次,a,2a,3a,...(p-1)a没有任何两个同余于模p的倍数。
        于是,a,2a,3a,...(p-1)a对模p的同余既不为0,也没有两个同余相同。因此,这p-1个数对模p的同余一定是1,2,3,...p-1的某一种排列,即:a*2a*3a*...*(p-1)a≡1*2*3*...*(p-1)(mod p)
        化简为:ap-1*(p-1)!≡(p-1)!(mod p)
        又由于p是素数,根据威尔逊定理得出(p-1)!和p互质。所以约去(p-1)!
        得到:ap-1≡1(mod p)
        其实这是一种特殊情形,一般情况下,若p为素数,则:ap≡a(mod p),这就是著名的费马小定理。    
        4.欧拉定理
  

    

   

        

 

     

      

 

 五、素数的判定

      1.穷举法
      int main(){
            int i,n;
            scanf("%d".&n);
            for(i=2;i<sqrt(n);i++)
                    if(n%i==0)break;
            if(i<n||n==1)puts("NO");
            else puts("Yes");
      }
       2.筛选法
         (1) 筛选法的具体做法是先把N个自然数按次序排列起来。首先排除1,1后面的第一个数是2,由于2是质数所以留下,并把后面所有2的倍数都去掉。2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。3后面第一个没划去的数是5,把5留下,再把5后面所有能被5整除的数都划去······以此类推,最后剩下的均为质数。
         (2)
    // 100 prime number
    // 筛选法 即:“埃拉托色尼筛选法”
    // 找出一个非素数就把它挖掉,最后剩下就是素数
    /*
      * 找出1~n的素数表
     * 1、挖去1
      * 2、用下一个未挖去的数p去除p后面各数,把p的倍数挖掉
      * 3、检查p是否小于n的整数部分(如果n=1000,则坚持p<31?),
     *    如果是,则返回(2)继续执行,否则结束。
      * 4、剩下的就是素数了
     */
      #include<iostream>
      #include<iomanip>
      #include<cmath>
      using namespace std;
      int main() {
        int i, j, n, a[101];
        for (i = 1; i <= 100; i++) {
          a[i] = i;
        }
        a[1] = 0;
        for (i = 2; i < sqrt(100); i++) {
          for (j = i + 1; j <= 100; j++) {
            if (a[i] != 0 && a[j] != 0) {
                if (a[j] % a[i] == 0) {
                    a[j] = 0;
                }
            }
        }
    }
    cout<<endl;
    for (i = 1, n = 0; i <= 100; i++) {
        if (a[i] != 0){
            cout<<setw(5)<<a[i]<<" ";
            n++;
        }
        if (n == 10) {
            cout<<endl;
            n = 0;
        }
    }
    cout<<endl;
    return 0;
}
       3.线性筛法
       (1)关于线性筛法

         线性是指O(n)内筛掉所有合数,还有一种方法叫埃氏筛法,我先证明埃氏筛法效率低,也就是会有重复。

         证明如下:

         埃氏筛法的原理是找到一个素数后,它的1~n倍就会被筛掉,任何一个合数都可以被拆成一个质数*另一个数的形式,我们对每一个质数对应的可能的(合)数都枚举了,这就保证了所有可能的合数都被筛掉了。为什么不是最优呢?问题出在那个质数上,对于一个合数m,m=h*P,P是质数且P>m的最小质因数,那么m也可以表示为m=H*p,(H是个比h大的合数,p是m的最小质因数),这样我们在枚举p的倍数时,m就被筛掉了,而在枚举P的倍数时,m又被筛掉了一次,造成效率浪费。

         怎办呢?--------线性筛法

         我们在枚举倍数时,保证当前质数不能整除这个倍数就好了,当然了,在之前要先筛一次,也就是p是m的p,这样我们在最优性的条件下,对每一个质数,它所有对应的倍数,都被枚举到,也就保证了可行性。

         #include<bits/stdc++.h>
    using namespace std;
    int n,cnt;
    int prime[100000];
    bool vis[100000];

    void Euler(){
        for(int i=2;i<=n;i++){
            if(!vis[i]) prime[++cnt]=i;
            for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
                vis[i*prime[j]]=1;
                if(i%prime[j]==0)
                break;
            }
         }
     }

    int main(){
      cin>>n;
      Euler();
      for(int i=1;i<=cnt;i++)
          cout<<prime[i]<<' ';
      return 0;
    }
       4.欧拉函数线性筛
       

   (1)欧拉函数有以下五条性质:

 

       

 

 

 

 

 

 由此,我们可以在素数线性筛的基础上筛出欧拉函数!

 每次想要得到phi[n],详细过程如下:

    若n为素数,根据①,有phi[n]==n-1

    若a*b==n(a,b为任意互质数),根据②,有phi[n]==phi[a]*phi[b],这里的phi[a]和phi[b]都是已经得到的

    若a*p==n(p为质数,且p是a的因数),根据⑤得phi[n]==phi[a]*p

 代码如下:

C++:

 

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int const MAXN=100010;
 6 
 7 int prime[MAXN],tot;
 8 bool notprime[MAXN];
 9 int euler[MAXN];
10 
11 void pony_getPhi(int n){ 
12     notprime[0]=1;
13     notprime[1]=1;
14     euler[1]=1;
15     for(int i=2;i<=n;++i){ 
16         if(!notprime[i])
17         {
18             prime[tot++]=i;
19             euler[i]=i-1;//HERE 1
20         }   
21         for(int j=0; j<tot && i*prime[j]<=n;++j){ 
22             notprime[i*prime[j]]=1; 
23             if(i%prime[j]==0){euler[i*prime[j]]=euler[i]*prime[j];break;}//HERE 5
24             else euler[i*prime[j]]=euler[i]*euler[prime[j]];//HERE 2
25         }
26      }
27 }
28 
29 int main(int argc,char *argv[],char *enc[]){
30     int m=100;
31     pony_getPhi(m);
32     for(int i=1;i<=m;++i){
33         printf("phi(%d):%d",i,euler[i]);
34         if(notprime[i]) printf("\n");
35         else printf("    [%d]Prime\n",i);
36     }
37     return 0;
38 }
5.莫比乌斯函数的线性筛法
莫比乌斯函数μ(d)的定义如下:
    (1)若d=1,那么μ(d)=1 
    (2)若d=p1p2…pk(p1…pk均为互异质数),那么μ(d)=(−1)^k 
    (3)其他情况下,μ(d)=0

  只要抓住定义就能轻松筛出莫比乌斯函数啦

  代码如下:

        #include<bits/stdc++.h>
        using namespace std;
       int const MAXN=100010;
       int prime[MAXN],tot;
       bool notprime[MAXN];
       int miu[MAXN];
       void pony_getMiu(int n){
           notprime[0]=1;
           notprime[1]=1;
          miu[1]=1;//HERE 1
          for(int i=2;i<=n;++i){
               if(!notprime[i])
               {
                   prime[tot++]=i;
                   miu[i]=-1;//HERE 2
              }
               for(int j=0; j<tot && i*prime[j]<=n;++j){
                  notprime[i*prime[j]]=1;
                   if(i%prime[j]==0){miu[i*prime[j]]=0;break;}//HERE 3
                  else miu[i*prime[j]]=-1*miu[i];//HERE 2
              }
           }
       }
       int main(int argc,char *argv[],char *enc[]){
          int m=100;
           pony_getMiu(m);
          for(int i=1;i<=m;++i){
               printf("miu(%d):%d",i,miu[i]);
               if(notprime[i]) printf("\n");
               else printf("    [%d]Prime\n",i);
          }
          return 0;
       }

      6.Miller-Rabin素数测试算法

  (1)作用:

   有时候我们想快速的知道一个数是不素数,而这个数又特别的大导致 O( \sqrt{n} ) 的算法不能通过,这时候我们可以对其进行 Miller-Rabin 素数测试,可以大概率测出其是否为素数。

  (2)两个基础理论

       证明转载费马小定律&二次探测的证明

    ①费马小定理:当 p 为质数,有 a^{p-1}\equiv 1(mod \: \, p),不过反过来不一定成立,也就是说,如果 ap 互质,且 a^{p-1}\equiv 1(mod \: \, p),不能推出 p 是质数,比如 Carmichael 数(这个就自行百度吧)

    ②二次探测:如果 p 是一个素数,0 < x < p, 则方程 x^{2}\equiv 1(mod\: \, p) 的解为 x = 1x = p - 1

         (3)算法流程
 

 

       (4)备注
        ①我们可以多选择几个 a,如果全部通过,那么 x 大概率是质数。
        ②Miller-Rabin 素数测试中,“大概率”意味着概率非常大,基本上可以放心使用。
        ③当 a 取遍小等于 30 的所有素数时,可以证明 int 范围内的数不会出错。
        ④代码中我用的 int 类型,不过实际上 Miller-Rabin 素数测试可以承受更大的范围。
        ⑤另外,如果是求一个 long long 类型的平方,可能会爆掉,因此有时我们要用“快速积”,不能直接乘。

 

  

 

 

 

 7.Pollard-Rho算法--大数分解

   

 

    

 

       

 

      

 

      

 

      

 

 


         参考:(仅限内部使用)

                    1.百度百科;

                    2.https://blog.csdn.net/forever_dreams/article/details/82314237

                    3.https://blog.csdn.net/ECNU_LZJ/article/details/72675595/

                    4.转载于:https://www.cnblogs.com/fzl194/p/9047710.htm

 

 



 

posted @ 2023-01-09 16:25  ddfy198811  阅读(785)  评论(0)    收藏  举报