1. 程式人生 > >數論1:簡單素數判斷

數論1:簡單素數判斷

復雜 式表 都是 log 但是 表達式 相同 成對 rime

假設我們要判斷的數為n,則有以下討論:

素數只能被1和本身整除,那麽試除\(O(n)\)

n非素數,其約數必成對出現,如3和12/3=4都是12的約數,3和9/3=3都是9的約數(這裏的成對可以相同),那麽我們只需考慮\(\le \sqrt n\)的數,得\(O(\sqrt n)\)

素數可以被分為兩類,偶素數和奇素數。偶素數只有2,所以我們在遍歷之前單獨判斷n是否被2整除,並將循環步長增置2,得\(O(\frac{\sqrt n}{2})\)

bool isprime(int n)
{
    if(n < 2) return 0;
    if(n == 2) return 1;
    if
(n % 2 == 0) return 0; int lim = sqrt(n); for(int i = 3; i <= lim; i += 2) if(n % i == 0) return 0; return 1; }

奇素數可以通過產生所有奇數的表達式產生,比如:\(4k+1\)\(4k+3\)能生成所有的奇數,所以這裏的步長可為4,得\(O(\frac{\sqrt n}{4})\)

bool isprime(int n)
{
    if(n < 2) return 0;
    if(n == 2) return 1;
    if(n % 2
== 0) return 0; int lim = sqrt(n); for(int i = 3; i <= lim; i += 4) if(n % i == 0) return 0; return 1; }

提前先判斷一部分奇數,減少後序循環中所需工作。比如\(6k+1\)\(6k+3\)\(6k+5\)
可生成所有奇數,提前判斷3,則可令步長為6,得\(O(\frac{\sqrt n}{6})\)

bool isprime(int n)
{
    if(n < 2) return 0;
    if(n < 4) return 1;
    if
(n % 2 == 0 || n % 3 == 0) return 0; if(n < 9) return 1; int lim = sqrt(n); // i+2是因為6k+5與6k-1同余,而6k-1與6k+1差2,所以+2 for(int i = 5; i <= lim; i += 6) if(n % i == 0 || n % (i+2) == 0) return 0; return 1; }

n若為合數,必能通過唯一形式的素數連乘形式表示(算術基本定理)
所以在上述方法中,不需考慮所以\(\le \sqrt n\)的數,僅考慮\(\le \sqrt n\)的素數即可,這裏的時間復雜度可達\(O(\lg \sqrt n)\)

但是,如何生成素數呢?

數論1:簡單素數判斷