素数篩
概要
エラトステネスの篩.
計算量
$1$から$N$までの全ての整数を素数判定する(篩の処理)場合は$\sqrt{N}\log \sqrt{N}$. この処理をすると,
- $N$以下の数の素因数分解が$O(\log N)$
$N$以下の数の約数列挙が$O(\log N)$(未実装)
で可能になる.
ソースコード
struct primeSieve{
vector<long> mfactor;
//既知の素数(随時追加される)
vector<long> primes;
set<long> primeSet;
long N;
primeSieve(){
N = 0;
calc();
}
primeSieve(long N){
this-> N = N;
calc();
}
/*
素数篩
O(sqrt(N))
*/
void calc(){
primes.clear();
mfactor.resize(N+1);
fill(mfactor.begin(),mfactor.end(),-1);
mfactor[0] = 0;
mfactor[1] = 1;
for(long i=2;i<=N;i++){
if(mfactor[i] == -1){
for(long j=i;j<=N;j+=i){
mfactor[j] = i;
}
}
}
for(long i=2;i<=N;i++){
if(mfactor[i] == i){
primes.push_back(i);
primeSet.insert(i);
}
}
}
/*
素数判定
O(1)
*/
bool isPrime(long x){
if(x==1)return false;
if(x<=N) return x == mfactor[x];
if(primeSet.count(x))return true;
return isPrimeNaive(x);
}
/*
Naive素数判定
O(sqrt(N))
*/
bool isPrimeNaive(long x){
if(x<=1)return false;
for(long i=2;i*i<=x;i++){
if(x%i==0){
return false;
}
}
primes.push_back(x);
primeSet.insert(x);
return true;
}
/*
素因数分解
O(log N)
*/
vector<long> factorization(long x){
if(x>N){
return factorizationNaive(x);
}
vector<long> A(0);
if(x==1){
A.push_back(1);
return A;
}
while(x>1){
A.push_back(mfactor[x]);
x /= mfactor[x];
}
reverse(A.begin(),A.end());
return A;
}
/*
Naive素因数分解
O(sqrt N)
*/
vector<long> factorizationNaive(long x){
vector<long> A(0);
for(long i=2;i*i<=x;){
if(x%i==0){
x/=i;
A.push_back(i);
}else{
i++;
}
}
if(x>1){
A.push_back(x);
}
return A;
}
}