Potencia rápida y elemento inverso

求 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.

Supongo que te gusta

Origin www.cnblogs.com/longxue1991/p/12725394.html
Recomendado
Clasificación