1. 程式人生 > >【C語言】求解素數(質數)的N種境界

【C語言】求解素數(質數)的N種境界

前言:

   眾所周知,不管是在學習、考試還是以後找工作中,對於求解素數的問題隨處可見,而且還是一個重難點,為何要說是重難點呢?主要是因為對於不同的人往往會有不同做法,但大多數掌握的都是一些非常平庸的做法,完全沒有技術含量。然而這對於我們這些技術人員無疑是一個BIG BUG。所以小編在此整理了一些求解套路,如有疑問,歡迎來擾。

★試除法

   首先要介紹的,當然非"試除法"莫屬啦。考慮到有些讀者沒聽過,小編在此稍微解釋一下:

"試除",顧名思義,就是不斷地嘗試能否整除。比如要判斷自然數 x 是否質數,就不斷嘗試小於 x 且大於1的自然數,只要有一個能整除,則 x 是合數;否則,x 是素數。
  顯然,試除法是最容易想到的思路。不客氣地說,也是最平庸的思路。不過呢,這個最平庸的思路,也有好多種境界。不信請看下文:

境界1//假設要判斷 x 是否為質數,就從 2 一直嘗試到 x-1。這種做法,其效率應該是最差的

#include<stdio.h>
#include<Windows.h>
int main()
{
   int i = 0,k = 0;
   int count = 0;
   for(i=100; i<=200; i++)
  {
     for(k=2; k<i; k++)
    {
       if(i%k == 0)
       break;
    }
     if(k == i)
     printf("%d是素數\n",i);
     count++;
   }
   printf("\n%4d",count);
   system("pause");
   return 0;}

境界2//所有素數都是偶數,因此可以加快步長

#include<stdio.h>
#include<Windows.h>
int main()
{
   int i = 0, k = 0;
   int count = 0;
   for(i=101; i<=200; i+=2)
  {
     for(k=2; k<i; k++)
    {
        if(i%k == 0)
        break;
    }
     if(k==i)
     printf("%d是素數\n",i);
     count++;
  }
   printf("\n%4d",count);
   system("pause");
   return 0;
}     

境界3//除了2以外,所有可能的質因數都是奇數。所以,他們就先嚐試 2,然後再嘗試從 3 開始一直到 x/2 的所有奇數

#include<stdio.h>
#include<Windows.h>
int main()
{
   int i = 0, k = 0;
   int count = 0;
   for(i=100; i<=200; i+=2)
  {
     for(k=2;k<i/2;k++)   
    {
        if(i%k == 0)
        break;
    }
     if(k==i)
     printf("%d是素數\n",i);
     count++;
  }
   printf("\n%4d",count);
   system("pause");
   return 0;
}     

境界4//其實只要從 2 一直嘗試到√簡單解釋一下:如,100的因數有:1和100,2和50,4和25,5和20,10和10

#include <stdio.h>
#include <math.h>
int main()
{
   int i = 0;
   int count = 0;
   for(i=100; i<=200; i++)
  {
     int j = 0;
     for(j=2; j<=sqrt(i); j++)
    {
        if(i%j == 0)
        break;
    }
     if(j>sqrt(i))
    {
     printf("%d ", i);
     count++;
    }
  }
   printf("\ncount = %d\n", count);
   return 0;
}

境界5//對於任意一個素數n,如果它有兩個質因子x,y,顯然n = x*y, 所以,由不等式性質可得,x <= sqrt(n), 即 x <= n^(1/2)。

#include <stdio.h>
#include <math.h>
int main()
{
    int i = 0;
    int count = 0;
    for(i=101; i<=200; i+=2)
   {
      int j = 0;
      for(j=2; j<=sqrt(i); j++)
     {
            if(i%j == 0)
               break;
     }
     if(j>sqrt(i))
     {
           count++;
           printf("%d ", i);
     }
   }
   printf("\ncount = %d\n", count);
   return 0;
}

★篩選法

  不知道的小夥伴請戳━>篩選法篩選法 ,真的是一個既巧妙又快速的求質數方法。其發明人是公元前250年左右的一位希臘大牛——埃拉託斯特尼。為什麼說他是大牛捏?因為他本人精通多個學科和領域,至少包括:數學、天文學、地理學(地理學這個詞彙,就是他創立的)、歷史學、文學(他是一個詩人)。真的堪稱"跨領域的大牛"。估計很多人把篩法僅僅看成是一種具體的方法。其實,篩法還是一種很普通的思想。在處理很多複雜問題的時候,都可以看到篩法的影子。那麼,篩法如何求質數捏,說起來很簡單:

先解釋一下篩選法的步驟:

<1> 先將1挖掉(因為1不是素數)。
<2> 用2去除它後面的各個數,把能被2整除的數挖掉,即把2的倍數挖掉。
<3> 用3去除它後面的各數,把3的倍數挖掉。
<4> 分別用5…各數作為除數去除這些數以後的各數。

上述操作需要一個很大的容器去裝載所有數的集合,只要滿足上述條件,即2的倍數大於1的全部置0,3的倍數大於1的全部置0,4的倍數大於1的全部置0.。。。一直到這個資料集合的末尾,這樣一來不為0的數就是素數了,然後按下標在裡面進行查詢就好了

光說不練假把式,貼出程式碼:

#include<stdio.h>
int main()
{
int i,j,a[100],e;
for(i=0;i<100;i++)
   a[i]=i+1;
for(i=0;i<100;i++)
	{
	j=i-1;
	while(j>1)
	{
	e=a[i]%j;
	if(e==0)a[i]=0;
	j=j-1;
	}
}
for(j=1;j<100;j++)
	{
		if(a[j]!=0)
		{
			printf("%2d ",a[j]);
		}
}
return 0;
}

 ●確定質數的分佈範圍

估計素數個數求解公式x/ln(x)(素數定理)誤差小於15%範圍越大,誤差越小

●儲存容器

境界1構造整形容器

100~200所有素數,除去所有合數剩下的就是素數

思想:篩去2,3,5,7,11,13的倍數,剩下的就是素數

境界2布林型容器

境界3按位(bit)儲存

小編目前還是菜鳥級別,如有不正之處,歡迎批評指正!

相關推薦

C語言求解素數質數N境界

★前言:   眾所周知,不管是在學習、考試還是以後找工作中,對於求解素數的問題隨處可見,而且還是一個重難點,為何要說是重難點呢?主要是因為對於不同的人往往會有不同做法,但大多數掌握的都是一些非常平庸的做

C語言簡單排序選擇排序

一、演算法框圖 二、程式碼實現 /******************** 名稱:選擇排序 作者:豆豆 ********************/ #include<stdio.h> #define LENGTH 6 //巨集定義數列長度為

C語言多項式加法mooc第七週測試題

  這個小題目吧我折磨的夠嗆,,主要在於特殊情況考慮不周,測試用例老是通不過。。 小結: 做法:用一個數組來儲存多項式,用下標表示冪次數,陣列元素值表示對應係數 輸出特殊格式考慮:係數和冪次數為0,1,-1的情況,負係數的對加號輸出的影響   題目內容:

C語言佇列演示佇列的幾個函式

/* * 佇列演示(佇列的幾個函式) * */ typedef struct { int arr[SIZE]; int head; //記錄最前面數字所在的下標 int tail; //記錄最後一個有效數字的下一個座標

C語言判斷素數函式

//方法一:2~m-1有沒有能整除的 int prime(int m) { int i; if(m==0) return 0; if(m==1) return 0;//考慮0和1的情況 for

C語言通訊錄程式碼一個檔案下實現

//【C語言】通訊錄(一個檔案實現)#include <stdio.h> #include <string.h> #define NAME_MAX 20 #define SEX_MAX 5 #define TEL_MAX 11 #define ADD

C#基礎關於類繼承

1、繼承:面向物件程式設計中提供的子類可以沿用父類某些行為和特徵的一種方式。       當一個類繼承另一個類時,被繼承的類稱為父類或基類;該類被稱為子類或派生類。       【特點】:        ⑴、傳遞性;(即類B繼承類A,類C繼承類B,故類C同時擁有類A和類

C++基礎----運算子過載01

一方面,在C++中,運算子過載( operator overloading)允許把標準運算子(如+  -  *  /  % 等)應用於自定義資料型別的物件。 這樣可以直觀自然地看出自定義資料型別間的運算,並且提高程式的可讀性。 另一方面,運算子過載僅僅是一種語法上的方便。

C語言數據對其內存對齊

brush size return () def ont http 之間 sign 數據對齊 結構體之間的對齊是有很多種方法的,也是根據你所用的系統位數有關。下面都是以32位系統來講的,32位系統一般以字對齊,字就是系統位數,32位系統則是32位對齊,也就是4字節(in

C語言 利用篩選法求100以內的素數

演算法思路: 原理很簡單,就是當i是質(素)數的時候,i的所有的倍數必然是合數。如果i已經被判斷不是質數了,那麼再找到i後面的質數來把這個質數的倍數篩掉。 程式碼如下: //C語言 篩選法求100以內的素數 //原理很簡單,就是當i是質(素)數的時候,i的所有的倍數必然是合數。如果i已經

C語言指標的算術運算指標+/-整數、指標+/-指標

一、指標+/-整數  在之前學習指標時,我們知道指標其實也是一種特殊的變數,既然這樣,那麼指標應該和普通變數一樣,可以進行算術運算。那問題就來了,是不是對指標的任何運算都是合法的呢? 答案是它可以執行某些運算,但並非所有的運算都合法。(指標可以進行加減法,對於乘除法是非法的)

C語言求Fibonacci數列的前20項陣列

//求Fibonacci數列的前20項 #include "stdio.h" int main(){     int i,j;     int f[20] = {1,1};//賦值數列前兩項     

C語言求一千以內的素數 第一方法

第一種方法:平常思維(人們第一印象會想到的)   //什麼是素數? -- 除了1和本身之外不能被其他數整除的數 #include "stdio.h" int main(){ int n,j,f;//變數解釋:n為我們要判斷的數,j為要與n相除的數,f為標誌 0 表示不是素數

C語言位元組對齊問題以32位系統為例

  1. 什麼是對齊?   現代計算機中記憶體空間都是按照位元組(byte)劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何地址開始,但實際情況是在訪問特定變數的時候經常在特定的記憶體地址訪問,這就需要各型別資料按照一定的規則在空間上排列,而不是順序地一個接一個地排放,這就是對齊

C語言實現一個計算器方式

1.使用switch…case…語句實現 #define _CRT_SECURE_NO_DEPRECATE 1 #include <stdio.h> #include <stdlib.h> int add(int x, int y) {   &nb

C語言輸入一個整數N,求N以內的素數之和

【C語言】輸入一個整數N,求N以內的素數之和   /* ============================================================================ Name

C語言實現對一個8bit資料unsigned char 型別的指定位例如第n的置0或者置1操作,並保持其他位不變

請編碼實現以下功能的函式 功能:實現對一個8bit資料(unsigned char 型別)的指定位(例如第n位)的置0或者置1操作,並保持其他位不變。 函式原型:void bit_set(unsigned char *p_data,unsigned char position,int flag)

c語言帶你真正走進指標的世界——陣列與指標的關係

       每天下課之後,都感覺老師上課在神仙程式設計,我們一群凡人在底下面無表情地走神,前一秒還是在講加減乘除的基本用法,後一秒就變成了指標陣列、陣列指標、結構體指標和N級指標的性質以及運用............(真是令人頭禿 —^—) ——————

javascript 顯示一定範圍內的素數質數

//<span style="font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 21.6000003814697px;">素數又稱質數,是大於1的自然數,並且只有1和它本身兩個因數。</span>

c語言利用指標模式實現字串函式strlen、strcat、strstr、strcpy、strcmp、memcpy、memove

模擬實現strlen int my_strlen(const char *p) { assert(p != NULL); char *s = p; while (*p) { p++; } r