On this page
article
Crivo de Eratosthenes
Sobre
“O” crivo
Encontra maior divisor primo
Um numero eh primo sse divi[x] == x
fact fatora um numero <= lim
A fatoracao sai ordenada
crivo - O(n log(log(n)))
fact - O(log(n))
Link original: crivo.cpp
Código
int divi[MAX];
void crivo(int lim) {
for (int i = 1; i <= lim; i++) divi[i] = 1;
for (int i = 2; i <= lim; i++) if (divi[i] == 1)
for (int j = i; j <= lim; j += i) divi[j] = i;
}
#warning A funcao fact ira adicionar o 1 no vetor se voce tentar fatorar especificamente o numero 1
void fact(vector<int>& v, int n) {
if (n != divi[n]) fact(v, n/divi[n]);
v.push_back(divi[n]);
}
// Crivo linear
//
// Mesma coisa que o de cima, mas tambem
// calcula a lista de primos
//
// O(n)
int divi[MAX];
vector<int> primes;
void crivo(int lim) {
divi[1] = 1;
for (int i = 2; i <= lim; i++) {
if (divi[i] == 0) divi[i] = i, primes.push_back(i);
for (int j : primes) {
if (j > divi[i] or i*j > lim) break;
divi[i*j] = j;
}
}
}
// Crivo de divisores
//
// Encontra numero de divisores
// ou soma dos divisores
//
// O(n log(n))
int divi[MAX];
void crivo(int lim) {
for (int i = 1; i <= lim; i++) divi[i] = 1;
for (int i = 2; i <= lim; i++)
for (int j = i; j <= lim; j += i) {
// para numero de divisores
divi[j]++;
// para soma dos divisores
divi[j] += i;
}
}
// Crivo de totiente
//
// Encontra o valor da funcao
// totiente de Euler
//
// O(n log(log(n)))
int tot[MAX];
void crivo(int lim) {
for (int i = 1; i <= lim; i++) {
tot[i] += i;
for (int j = 2*i; j <= lim; j += i)
tot[j] -= tot[i];
}
}
// Crivo de funcao de mobius
//
// O(n log(log(n)))
char meb[MAX];
void crivo(int lim) {
for (int i = 2; i <= lim; i++) meb[i] = 2;
meb[1] = 1;
for (int i = 2; i <= lim; i++) if (meb[i] == 2)
for (int j = i; j <= lim; j += i) if (meb[j]) {
if (meb[j] == 2) meb[j] = 1;
meb[j] *= j/i%i ? -1 : 0;
}
}
// Crivo linear de funcao multiplicativa
//
// Computa f(i) para todo 1 <= i <= n, sendo f
// uma funcao multiplicativa (se gcd(a,b) = 1,
// entao f(a*b) = f(a)*f(b))
// f_prime tem que computar f de um primo, e
// add_prime tem que computar f(p^(k+1)) dado f(p^k) e p
// Se quiser computar f(p^k) dado p e k, usar os comentarios
//
// O(n)
vector<int> primes;
int f[MAX], pot[MAX];
//int expo[MAX];
void sieve(int lim) {
// Funcoes para soma dos divisores:
auto f_prime = [](int p) { return p+1; };
auto add_prime = [](int fpak, int p) { return fpak*p+1; };
//auto f_pak = [](int p, int k) {};
f[1] = 1;
for (int i = 2; i <= lim; i++) {
if (!pot[i]) {
primes.push_back(i);
f[i] = f_prime(i), pot[i] = i;
//expo[i] = 1;
}
for (int p : primes) {
if (i*p > lim) break;
if (i%p == 0) {
f[i*p] = f[i / pot[i]] * add_prime(f[pot[i]], p);
// se for descomentar, tirar a linha de cima tambem
//f[i*p] = f[i / pot[i]] * f_pak(p, expo[i]+1);
//expo[i*p] = expo[i]+1;
pot[i*p] = pot[i] * p;
break;
} else {
f[i*p] = f[i] * f[p];
pot[i*p] = p;
//expo[i*p] = 1;
}
}
}
}