日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ACM数论-素数

發布時間:2024/7/19 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ACM数论-素数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ACM數論——素數?


?

素數定義

? ? ? ? 質數(prime number)又稱素數,有無限個。質數定義為在大于1的自然數中,除了1和它本身以外不再有其他因數,這樣的數稱為質數。例 子:2、3、5、7、11、13、17、19。(那時候還有一種說法叫做“質數”,但是就語言上來說,我覺得“素數”這種叫法和“合數”比較搭配,類比于“化學元素”和“化合物”來看,叫“素數”非常貼切)

素數一些性質:

  • 質數p的約數只有兩個:1和p;
  • 任一大于1的自然數,要么本身是質數,要么可以分解為幾個質數之積,這種分解是唯一的;
  • 一個偶數可以寫成兩個合數之和,其中每一個合數都最多只有9個質因數;
  • 一個偶數必定可以寫成一個質數加上一個合成數,其中合數的因子個數有上界;
  • 素數應用:

  • ?數學上來看,質數有很多尚未證明的特性;應用上的話,公鑰密碼是一比較好的例子了。
  • 素數對于數論就好像元素對于化學。(摘自知乎)
  • ?判斷素數:

    1 //判斷是否是一個素數 2 int IsPrime(int x) 3 { 4 if(x<=1) //0,1,負數都是非素數 5 return 0; 6 int ans=(int)sqrt(x)+1; /*計算枚舉上界,為防止ans值帶來的精度損失,所以采用根號值取整后再加1,即寧愿多枚舉一個,也不愿少枚舉一個數 */ 7 for(int i=2; i<ans; i++) 8 { 9 if(x%i==0) 10 { 11 return 0; 12 } 13 } 14 return 1; 15 } View Code

    ?素數篩法:

      1.開一個大的bool型數組prime[],大小就是n+1就可以了.先把所有的下標為奇數的標為true,下標為偶數的標為false.

      2.代碼如下:

    for( i=3; i<=sqrt(n); i+=2 ) { if(prime[i]) for( j=i+i; j<=n; j+=i )prime[j]=false;}

    ??? 3.最后輸出bool數組中的值為true的單元的下標,就是所求的n以內的素數了。
    ???   原理很簡單,就是當i是質(素)數的時候,i的所有的倍數必然是合數。如果i已經被判斷不是質數了,那么再找到i后面的質數來把這個質數的倍數篩掉。?
    ??? 一個簡單的篩素數的過程:n=30。

    ??? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30


    ??? 第 1 步過后4 ... 28 30這15個單元被標成false,其余為true。
    ??? 第 2 步開始:
    ???? i=3; 由于prime[3]=true, 把prime[6], [9], [12], [15], [18], [21], [24], [27], [30]標為false.
    ???? i=4; 由于prime[4]=false,不在繼續篩法步驟。
    ???? i=5; 由于prime[5]=true, 把prime[10],[15],[20],[25],[30]標為false.
    ???? i=6>sqrt(30)算法結束。
    ??? 第 3 步把prime[]值為true的下標輸出來:
    ???? for(i=2; i<=30; i++)
    ????   if(prime[i]) printf("%d ",i);
    ??? 結果是 2 3 5 7 11 13 17 19 23 29

      下圖為n=120的素數篩:

    // 1:這是最原始的素數篩法 #define Max 1000000 bool prime[Max]; void IsPrime(){prime[0]=prime[1]=0;prime[2]=1;for(int i=3;i<max;i++)prime[i]=i%2==0?0:1;int t=(int)sqrt(Max*1.0);for(int i=3;i<=t;i++)if(prime[i])for(int j=i;j<Max;j+=i)prime[j]=0; } //2:優化后的篩法,手動地模擬原始篩法就可以發現,某個數字可能被不止一次地刪去 // 優化后的篩法就可以避免這種不必要的刪去操作 #define Max 1000000 bool prime[Max]; void IsPrime(){prime[0]=prime[1]=0;prime[2]=1;for(int i=3;i<max;i++)prime[i]=i%2==0?0:1;int t=(int)sqrt(Max*1.0);for(int i=3;i<=t;i++)if(prime[i])for(int j=i*i;j<Max;j+=2*i)//優化 prime[j]=0; } View Code

    ?快速線性篩法?:

      上面的方法比較好理解,初始時,假設全部都是素數,當找到一個素數時,顯然這個素數乘上另外一個數之后都是合數

      把這些合數都篩掉,即算法名字的由來。但仔細分析能發現,這種方法會造成重復篩除合數,影響效率。

      比如10,在i=2的時候,k=2*15篩了一次;在i=5,k=5*6 的時候又篩了一次。所以,也就有了快速線性篩法。

      利用了每個合數必有一個最小素因子。每個合數僅被它的最小素因子篩去正好一次。所以為線性時間。

    void get_prime() {int cnt = 0;for (int i = 2; i < N; i++){if (!tag[i]) p[cnt++] = i;for (int j = 0; j < cnt && p[j] * i < N; j++){tag[i*p[j]] = 1;if (i % p[j] == 0)break;}} } 函數模板 1 我推薦這個算法! 易于理解,只算奇數部分,時空效率都還不錯! 2 half=SIZE/2; 3 int sn = (int) sqrt(SIZE); 4 for (i = 0; i < half; i++) 5 p[i] = true;// 初始化全部奇數為素數。p[0]對應3,即p[i]對應2*i+3 6 for (i = 0; i < sn; i++) { 7 if(p[i])//如果 i+i+3 是素數 8 { 9 for(k=i+i+3, j=k*i+k+i; j < half; j+=k) 10 // 篩法起點是 p[i]所對應素數的平方 k^2 11 // k^2在 p 中的位置是 k*i+k+i 12 // 下標 i k*i+k+i 13 //對應數值 k=i+i+3 k^2 14 p[j]=false; 15 } 16 } 17 //素數都存放在 p 數組中,p[i]=true代表 i+i+2 是素數。 18 //舉例,3是素數,按3*3,3*5,3*7...的次序篩選,因為只保存奇數,所以不用刪3*4,3*6.... 推薦

    ?


    ?

    轉載于:https://www.cnblogs.com/slp0622/p/8998445.html

    總結

    以上是生活随笔為你收集整理的ACM数论-素数的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。