尤拉篩
阿新 • • 發佈:2021-11-13
尤拉篩
質數篩
也稱線性篩
它比時間複雜度為 \(O(n\log\log n)\) 的埃氏篩更優,因為埃氏篩會有篩重。
尤拉篩保證每個合數只會被它的最小質因數篩掉,所以每個數只會被篩一次。
時間複雜度 \(O(n)\)
#include <vector> #include <bitset> std::vector<int> prime;//存放篩出來的質數 std::bitset<100000003> cmpst;//是否是合數(composite) inline void Euler(register int n) { cmpst.reset(); for (register int i=2; i<=n; ++i) { if (!cmpst[i]) prime.push_back(i);//不是合數 for (register int p : prime) { if (i * p > n) break; cmpst[i*p] = 1;//標記合數 if (i % p == 0) break;//核心操作:此時p是i的最小質因數 } } }
尤拉函式篩
特殊地,對於一個質數 \(p\) ,有 \(\varphi(p)=p-1\)
同時,因為尤拉函式 \(\varphi\) 是積性的,所以有 \(\forall\gcd(a,b)=1,\ \varphi(a\times b)=\varphi(a)\times\varphi(b)\)
又因為對於任意兩個質數 \(p_1,p_2\) ,必有 \(\gcd(p_1,p_2)=1\) ,所以我們考慮用質數篩出合數的 \(\varphi\) 值。
時間複雜度 \(O(n)\)
#include <vector> #include <bitset> template<int N> class Phi { private: int n, phi[N]; std::vector<int> prime; std::bitset<N> cmpst;//composite; void Euler() { cmpst.reset(); phi[1] = 1; for (register int i=2, tmp; i<=n; ++i) { if (!cmpst[i]) { prime.push_back(i); phi[i] = i-1;//質數的phi值 } for (register int p : prime) { tmp = i*p; if (tmp > n) break; cmpst[tmp] = 1;//標記合數 if (i%p == 0) {//同樣的核心操作 phi[tmp] = phi[i] * p; break; } phi[tmp] = phi[i] * phi[p];//合數的phi值,利用phi的積性 } } } public: Phi() : n(N<1?0:N-1) { Euler(); } Phi(int _n) : n(_n) { Euler(); } void build(int _n) { n = _n, Euler(); } int operator () (int x) const { return phi[x]; } int max_n() const { return n; } };
本文來自部落格園,作者:Gyan083,轉載請註明原文連結:https://www.cnblogs.com/gyan083/p/15549884.html