求 a ^ k% p , (1 <= a, k, p <= 10 ^ 9)
#include <iostream> #include <algorithm> usando el espacio de nombres std; typedef largo largo LL; LL qmi ( int a, int b, int p) { LL res = 1 ; mientras que (b) { if (b & 1 ) res = res * a% p; b >> = 1 ; a = (LL) a * a% p; } return res; } int main () { int n; cin >> n; mientras que (n-- ) { int a, b, p; cin >> a >> b >> p; cout << qmi (a, b, p) << endl; } }
Si usa violencia, es O (n) = 10 ^ 9, y la potencia rápida es nivel log, log10 ^ 9 = 30;
El principio es: por ejemplo, 4 ^ 5 = 4 ^ 2 ^ 0 + 4 ^ 2 ^ 2,
El primer paso es generar 4 ^ 2 ^ 0 = 4 mod 10;
El segundo paso genera 4 ^ 2 ^ 1 = 6 mod 10;
El tercer paso es dar a luz 4 ^ 2 ^ 2 = 6 mod 10;
Puedes ver que cada paso es el cuadrado del frente, entonces el ayuno es el mismo. Al principio, la base a = a, a = a * a = a ^ 2, a = a ^ 2 * a ^ 2 = a ^ 4, a = a ^ 4 * a ^ 4 = a ^ 8;
Si hay 1, entonces (a & 1) res = res * a; a >> = 1; a = a * a% p;
Nota: Siempre olvidaré la condición if (a & 1). 4 ^ 101, res = 4, res = 4 * 4 ^ 4 = 4 ^ 5; entonces el exponente se ve como una suma, pero cuando se agrega al fondo, se cuadra continuamente y luego se multiplica por el producto anterior.
res = 1; if (a & 1) res = res * a% p; a >> = 1; a = a * a;
Congruencia inversa:
congruencia a / b a * x mod m
b * x congruencia 1 mod m
Teorema de Fermat: b y p son relativamente primos, entonces b ^ p-1 es congruente p. (Por ejemplo, 2 ^ (3-1) = 4% 3 = 1, 2 ^ (5-1) = 16% 5 = 1, 5 ^ (3-1) = 25% 3 = 1, 3 ^ (5-1 ) = 81% 5 = 1)
b * b ^ p-2 congruencia p
Entonces el inverso multiplicativo de b% p es b ^ p-2. (Si el resto de byp no es 0, entonces no debe haber un elemento inverso) (Si byp son relativamente primos, entonces debe haber un elemento inverso b ^ (p-2) según el teorema de Fermat, porque ambos números primos son> = 2)
Para que pueda usar el poder rápido para encontrar:
#include <iostream> #include <algorithm> #include <cstdio> typedef long long LL; usando el espacio de nombres estándar; int qmi ( int a, int p, int k) { int res = 1 ; mientras que (p) { if (p & 1 ) res = (LL) res * a% k; p >> = 1 ; a = (LL) a * a% k; } return res; } intmain () { int n; scanf ( " % d " , & n); mientras que (n-- ) { int a, p; scanf ( " % d% d " , & a, & p); int res = qmi (a, p - 2 , p); if (a% p) printf ( " % d \ n " , res); else printf ( " imposible \ n " ); } }
int res = qmi (a, p-2 , p);
if (a% p) printf ("% d \ n" , res);
Tenga en cuenta que no puede juzgar si el resultado devuelto por res es 0 o 1 porque si un = 2, p = 2, es igual a 1, por lo que depende de si a y p no son compuestos.