素數
素數:一個整數大於1除了1和它自己,沒有其他約數即為素數
數學語言:\(\forall n \in Z^+ 且 n>=2 同時只存在1|n,n|n\)
與之相反,合數的定義即為除了1和它自己還有約數
小知識:素數只有2和素奇數
素數篩法
窮舉法
及枚舉\((1,n)\)的所有數,如果某個數能整除則不是素數
優化:枚舉區間\((1,\sqrt n]\)
簡單說明:一個數的一對因數(我們定義這對因數乘積為n)要么大於\(\sqrt n\)要么小於\(\sqrt n\),所以只用枚舉小於\(\sqrt n\)的因數枚舉完即可
不存在一對因數同時小於\(\sqrt n\) 如果小於兩數乘積勢必小於\(n\)
舉例
\(n=16\)
\(n\)的因數:\(1,16,2,8,4,4\)
分成每對\((1,16)(2,8)(4,4)\)
只用枚舉\((1,4]\)即可
埃氏篩法
埃氏篩法的核心便是找到一個素數后,篩去這個素數的倍數,(用數組標記),因為這個素數的倍數一定不為素數(合數)
但是埃氏篩法會重復篩合數,會影響效率
比如30,發現2是素數時,會篩去30,但又發現5是素數時,又會再篩去一次
歐拉篩法
歐拉篩法便優化了埃氏篩法,使得每個合數只被篩去一次
- 先介紹一個素數定理,任一合數可以表現為若干素數積
簡單說明:一個合數一定可以分成除了1和它本身以外的因數,而其他因數可以為素數或者合數,那么合數還是可以分為素數或合數,所以不斷的拆分成,直到全為素數
根據這個定理我們可以規定,一個合數可以等於它的最小質因數×某個合數或素數
合數=min(素數)×(合數或素數)
歐拉篩法會用一個數組(isprime[])依次存放素數,此時的素數數組是遞增的
那么設x=i*isprime[j]
\(isprime[j]\)一定為素數,i為素數或合數
所以假設\(isprime[j]\)為最小素因數,所以i的因數中不能有小於\(isprime[j]\)的因數(除了1)
所以只需要判斷 \(i%isprime[j]==0\) 是否成立即可
當然也可以反證
假設\(i%isprime[j]==0\)
因為\(isprime[]\)是遞增的
則合數\(i*isprime[j+1]=isprime[j]*(k*isprime[j+1])(k=i/isprime[j])\)
- \(k>isprime[j]\)簡單說明 因為合數被表示為最小質因數*某個合數,此時合數\(i*pirme[j]\)中,\(prime[j]\)為最小質因數,\(i\)為某個合數,根據我們的規定,i中的因數不能有小於\(prime[j]\)的,所以\(i\)的因數\(prime[j]\)和\(k\)都大於或等於\(prime[j]\)
其中\(isprime[j]<isprime[j+1]\) 所以isprime[j]為最小質因數,這個合數被isprime[j](kisprime[j+1])已經篩掉了,大於\(isprime[j]\)同理,所以不同再篩了
[線性篩模板(https://www.luogu.com.cn/problem/P3383)
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxx=100000000+10;
int s[6000000+10];
bool isprime[maxx];
int main(){
int n,q;
std::ios::sync_with_stdio(0);
cin>>n>>q;
int top=1;
memset(isprime,1,sizeof(isprime));
isprime[1]=0;
for(int i=2;i<=n;++i){
if(isprime[i])
s[top++]=i;
for(int j=1;j<=top && i*s[j]<=n;++j){
isprime[i*s[j]]=0;
if(i%s[j]==0) break;
}
}
for(int i=1;i<=q;++i){
int pl;
cin>>pl;
cout<<s[pl]<<endl;
}
return 0;
}
相關定理
惟一分解定理
若整數\(a>=2\),那么a一定可以表示為若干個素數的乘積(惟一的形式)即 \(a=p_1^{a_1}*p_2^{a_2}*p_3^{a_3}*......*p_n^{a_n}(\forall p \in 素數,\forall a_i \in Z^{+})\)
例如\(48=2^4*3\)
威爾遜定理
若p為素數 則\((p-1)!=-1(\mod p)\)
威爾遜定理的逆定理同樣成立
即:若某一正整數p,\((p-1)!=-1(\mod p)\)則p一定為素數
證明(見其他博客吧)(我真的證不來)
- 應用
根據威爾遜定理則\(p|((p-1)!+1)\),利用sin函數特點,構造出一個素數函數分布曲線
\(f(n)=sin(Π*((n-1)!+1)/n)\)使函數值為0的點就是素數\((Π為pai)\)
費馬小定理
若\(p\)為素數,\(a\)為正整數,且\(gcd(a,p)=1\)則\(a^{p-1}=1(\mod p)\)
-
證明
取\((p-1)\)個整數\(a,2a,3a,.......,(p-1)a\),其中任一整數都不是p的倍數,且皆不同余於模p則構造素數P的完全剩余系
$ P=$ {$ 1,2,.....,p-1$}
即可構造又一個A的完全剩余系
$ A=$ {$ a,2a,.....,(p-1)a$}
(解釋,\(gcd(a,p)=1\),\(a*x(\forall x<(p-1))\),又因為P的完全剩余系中兩兩互不同余於p,則利用同乘性,A的完全剩余系兩兩互不同余)
由完全剩余系定義
\(a*2a*3a*.....*(p-1)a=1*2*3....*(p-1)(\mod p)\)
化簡
\((p-1)!*a^{p-1}=(p-1)!(\mod p)\)
則\(a^{p-1}=1(\mod p)\)
p為整數時\(a^p =a (\mod p)\)