Todo sobre números primos
Un número primo es un número natural mayor que 1 que no tiene divisores positivos distintos de 1 y en sí mismo.
Compruebe si n es un múltiplo de cualquier número entero entre 2 yn.
#define ll largo largo
#define M (x, i) memset (x, i, sizeof (x))
para (i = 2; i <n; ++ i) if (n% i == 0) break;
cout << (i == n? "Número primo": "No es primo");
- ¿Cuál es un buen algoritmo para interpolar datos de series temporales faltantes?
- ¿Qué es la eficiencia del algoritmo?
- ¿Cuáles son algunos algoritmos de gráficos más utilizados en aplicaciones del mundo real?
- ¿Qué es la técnica Hashing?
- ¿Cuáles son las aplicaciones en tiempo real del algoritmo de Dijkstra?
Complejidad de tiempo: O (n)
Cada número compuesto tiene al menos un factor primo menor o igual a la raíz cuadrada de sí mismo.
Esta propiedad se puede probar usando la declaración de contador. Deje a y b ser dos factores de n tales que a * b = n. Si ambos son mayores que sqrt (n), entonces ab> sqrt (n), * sqrt (n), lo que contradice la expresión “a * b = n”.
Compruebe si n es múltiplo de cualquier número entero entre 2 y sqrt (n).
para (i = 2; i <sqrt (n); ++ i) if (n% i == 0) break;
cout << (i == n? "Número primo": "No es primo");
Complejidad de tiempo: O (sqrt (n))
Otro enfoque para verificar si un número es primo o no es usar una prueba probabilística. Es decir, lleva a cabo algunas pruebas y determina con cierto grado de certeza si es primordial o no.
Prueba de primalidad de Fermat:
“Si p es un número primo, entonces para cualquier número entero a, a ^ p – a será divisible por p”.
es decir, a ^ p = a mod p
ll módulo (ll a, ll b, ll c) {
// calcular (a ^ b)% c
ll x = 1;
ll y = a;
mientras que (b> 0) {
si (b & 1) x = (x * y)% c;
y = (y * y)% c;
b = b >> 1;
}
retorno x% c;
}
bool Fermat (ll p, int iteraciones) {
if (p == 1) devuelve 0;
para (int i = 0; i <iteraciones; i ++) {
// elige un entero aleatorio entre 1 y p-1 (inclusive)
ll a = rand ()% (p-1) +1;
if (módulo (a, p-1, p)! = 1) devuelve 0; / * p es definitivamente compuesto * /
}
retorno 1; / * p es probablemente primo * /
}
Complejidad de tiempo: O (log (n))
Prueba de primalidad de Miller-Rabin.
Si p es primo y x ^ 2 = 1 (mod p), entonces x = +1 o -1 (mod p). Podríamos probar esto de la siguiente manera:
x ^ 2 = 1 (mod p)
x ^ 2 – 1 = 0 (mod p)
(x-1) (x + 1) = 0 (mod p)
Ahora bien, si p no divide tanto (x-1) como (x + 1) y divide su producto, entonces no puede ser un primo, lo cual es una contradicción. Por lo tanto, p dividirá (x-1) o dividirá (x + 1), entonces x = +1 o -1 (mod p).
Supongamos que p es el número dado que tenemos que probar para primalidad. Primero reescribimos p-1 como (2d) * s. Ahora elegimos algunos a en el rango [1, n-1] y luego verificamos si as = 1 (mod p) o a (s * (2r)) = -1 (mod p). Si ambos fallan, entonces p es definitivamente compuesto. De lo contrario, p es probablemente primo. Podemos elegir otra a y repetir la misma prueba. Podemos detenernos después de un número fijo de iteraciones y afirmar que o p es definitivamente compuesto, o probablemente sea primo.
int prime [] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79, 83,89,97};
ll mulmod (ll a, ll b, ll c) {// return (a * b)% c O (log (N))
ll x = 0, y = a% c;
mientras que (b> 0) {
si (b% 2 == 1) x = (x + y)% c;
y = (y * 2)% c;
b / = 2;
}
retorno x% c;
}
ll mulmodfast (ll a, ll b, ll mod) {// return (a * b)% mod O (1)
a% = mod;
b% = mod;
largo doble res = a;
res * = b;
ll c = (ll) (res / mod);
a * = b;
a – = (c * mod);
a% = mod;
si (a <0) a + = mod;
devolver a;
}
ll módulo (ll a, ll b, ll c) {
ll x = 1, y = a; // se toma mucho tiempo para evitar el desbordamiento de resultados intermedios
mientras que (b> 0) {
if (b% 2 == 1) x = mulmod (x, y, c); // podemos usar mulmod o multiplicar fxn aquí
y = mulmod (y, y, c); // cuadrando la base
b / = 2;
}
retorno x% c;
}
bool Miller (ll p, int iteración) {
si (p <2) devuelve 0;
if (p! = 2 && p% 2 == 0) devuelve 0;
para (int i = 0; i <25; i ++) {
if (p == prime [i]) devuelve 1;
de lo contrario si (p% primo [i] == 0) devuelve 0;
}
largo largo s = p-1;
mientras que (s% 2 == 0) s / = 2;
para (int i = 0; i <iteración; i ++) {
largo largo a = rand ()% (p-1) + 1, temp = s;
largo largo mod = módulo (a, temp, p);
while (temp! = p-1 && mod! = 1 && mod! = p-1) {
mod = mulmod (mod, mod, p);
temp * = 2;
}
if (mod! = p-1 && temp% 2 == 0) devuelve 0;
}
retorno 1;
}
Complejidad de tiempo: O (log (n))
Tamiz de Eratóstenes: Encontrar todos los números primos del 2 al n.
Un algoritmo para hacer tablas de primos. Escriba secuencialmente los enteros del 2 al número más alto n que desea incluir en la tabla. Tacha todos los números> 2 que son divisibles por 2 (cada segundo número). Encuentra el número restante más pequeño> 2. Es 3. Así que tacha todos los números> 3 que son divisibles por 3 (cada tercer número). Encuentra el número restante más pequeño> 3. Es 5. Entonces tacha todos los números> 5 que son divisibles por 5 (cada quinto número).
Continúe hasta que haya tachado todos los números divisibles por sqrt (n).
// no estamos eliminando múltiplos de 2 considéralo elf
#define MAX 65536
#define LMT 256
bandera de bool1 [MAX];
int prime [MAX];
tamiz nulo1 () {
int i, j, k;
flag1 [0] = flag1 [1] = 1;
para (i = 3; i <LMT; i + = 2) {
k = i << 1;
para (j = i * i; j <MAX; j + = k) {
flag1 [j] = 1;
}
}
primo [0] = 2;
j = 1;
para (i = 3; i <MAX; i + = 2)
if (! flag1 [i])
primo [j ++] = i;
}
Complejidad de tiempo: O (nlog (n))
Memoria y tiempo eficiente:
bandera sin firmar [MAX / 64];
primos sin signo [MAX / 10];
prima sin signo;
#define ifC (n) (flag [n >> 6] & (1 <> 1) & 31)))
#define isC (n) (flag [n >> 6] | = (1 <> 1) & 31)))
#define chk (n) (n == 2 || (n> 2 && (n & 1) &&! ifC (n))) // indica si un número es primo o no
Ok, sí, claramente está cambiando un poco. Pero primero debe saber qué hacemos en un tamiz bit a bit para obtener esto. En lugar de usar una posición de matriz completa para almacenar solo un indicador, podemos usar cada uno de sus 32 bits para almacenar un indicador, lo que ahorra memoria en un factor 1/32. Entonces, es muy lógico capturar memoria hasta MAX / 32, pero ¿por qué MAX / 64 aquí?
Porque, realmente no tenemos ningún punto de manejar el número par ya que 2 es el único primo par y podemos manejarlo manualmente, sin ningún tipo de estrés. Entonces, si no consideramos los números pares en absoluto, los números totales se reducen nuevamente en un factor 1/2, ¿no es así? Entonces, lo que obtenemos es MAX / 32/2 = MAX / 64.
Ahora, las dos macros ifC e isC son bastante sencillas. ifC comprueba si un indicador de bits específico es 1 o 0, e isC establece un indicador de bits específico 1 para marcarlo como compuesto.
En el tamiz bit a bit, ¿dónde se encuentra un valor específico n? Obviamente (n / 32) th índice, y en ese índice, (n% 32) th bit de LSB (lado derecho).
tamiz vacío () {
sin signo i, j, k;
para (i = 3; i <LMT; i + = 2)
if (! ifC (i))
para (j = i * i, k = 2 * i; j <MAX; j + = k)
isC (j);
primos [0] = 2;
para (i = 3, j = 1; i <MAX; i + = 2)
if (! ifC (i))
primos [j ++] = i;
primo = j;
}
Complejidad de tiempo: O (n * log (n))
Más eficiente 🙂
Cada número primo puede expresarse en forma de 6 * x + 1 o 6 * x-1, excepto 2 y 3.
bandera sin firmar [MAX / 64];
primos sin signo [MAX / 10];
prima sin signo;
#define ifC (n) (flag [n >> 6] & (1 <> 1) & 31)))
#define isC (n) (flag [n >> 6] | = (1 <> 1) & 31)))
#define chk (n) (n == 2 || (n> 2 && (n & 1) &&! ifC (n))) // indica si un número es primo o no
tamiz vacío () {
sin signo i, j, k, l;
para (j = 9; j <MAX; j + = 6) {
isC (j);
}
para (i = 5; i <LMT; i + = 6) {
l = i + 2;
if (! ifC (i)) {
para (j = i * i, k = 2 * i; j <MAX; j + = k) {
isC (j);
}
}
if (! ifC (l)) {
para (j = l * l, k = 2 * l; j <MAX; j + = k) {
isC (j);
}
}
}
primos [0] = 2;
primos [1] = 3;
para (k = 5, j = 1; k <MAX; k + = 6) {
if (! ifC (k))
primos [++ j] = k;
if (! ifC (k + 2))
primos [++ j] = k + 2;
}
primo = j;
}
Complejidad de tiempo: O (n * log (n))
Tamiz segmentado: encontrar números primos en un rango.
// encontrando primos entre [l … .u]
vacío segmented_sieve (int l, int u) {
int i, j, d, sqlmt;
d = u-l + 1;
bandera de bool [d]; // la bandera [i] muestra que l + i es primo o no
M (bandera, 0);
para (i = (l% 2! = 0); i <d; i + = 2) indicador [i] = 1; // podemos omitir estas líneas si queremos
sqlmt = sqrt (u);
para (i = 3; i <= sqlmt; i + = 2) {
if (i> l && flag [il]) continuar;
j = (l / i) * i;
si (j <l) j + = i;
si (j == i) j + = i;
para (j = jl; j <d; j + = i) bandera [j] = 1;
}
if (l <= 1) flag [1-l] = 1;
if (l <= 2) flag [2-l] = 0;
}