質數又稱做素數.
質數是除了1和自己沒有其餘因數的數.
與之相反的是合數.
1不屬於質數或合數.函數
假設咱們要判斷\(n\)是否是質數.
從2枚舉\(n-1\),若能整除\(n\),\(n\)就不是質數.
時間複雜度\(O(n)\).
但因數是成對的(除了\(\sqrt n\))
令\(n=c_1 c_2\),假設\(c_1 \le c_2\)
則\(c_1 \le \sqrt n , c_2 \ge \sqrt n\)
因此只需枚舉到\(\sqrt n\).spa
bool isprime(long long x) { for(int i=2; i<=sqrt(x); i++) { if(x%i==0) return false; } return true; }
時間複雜度\(O(\sqrt n)\).code
如今咱們要求\(1\)到\(n\)中所有質數.class
最簡單的辦法就是判斷每一個數是否爲質數.
時間複雜度\(O(n \sqrt n)\).im
從\(1\)到\(\sqrt n\),若這個數沒有被標記,即爲質數.
只要發現了一個質數\(t\),就把從\(1\)到\(n\)中所有\(t\)的倍數標記.
時間複雜度\(O(n \log n)\)時間
對於每一個\(i(1<i<n)\),篩去全部小於\(i\)的質數與\(i\)的乘積.
不難發現,有些合數被重複篩去.
設全部小於\(i\)的質數分別爲\(p_1,p_2,...,p_j\).
當\(i\)%\(p_k=0\)時,中止篩\(i\)的倍數,便可避免重複.
由於當\(l>k\)時,全部\(i*p_l\)都會被比\(i\)大的數與\(p_k\)的乘積篩去.vi
for(int i=2;i<=n;i++){ if(!vis[i]) { cnt++; pri[cnt]=i; } for(int j=1;i*pri[j]<=n;j++){ vis[i*pri[j]]=true; if(i%pri[j]==0) break; } }
時間複雜度\(O(n)\)while
一個數的質因數一定小於等於\(\sqrt n\).
只需把\(i\)從\(2\)枚舉到\(\sqrt n\),從\(n\)中去掉全部\(i\)並作記錄,就能求出\(n\)的質因數.co
for(int i=2;i<=sqrt(n);i++) { while(n%i==0) { n/=i; cnt[i]++; } }
時間複雜度\(O(\sqrt n)\)block
歐拉函數是從\(1\)到\(n-1\)的數中與\(n\)互質的數的個數.
1.對於質數\(n\),\(φ(n)=n-1\).
2.對於質數\(p\),\(φ(p^k)=(p-1)*p^{k-1}\).
hasn't finished