數論1:簡單素數判斷
阿新 • • 發佈:2018-03-07
復雜 式表 都是 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:簡單素數判斷