求 a ^ k% p , (1 <= a, k, p <= 10 ^ 9)
#include <iostream> #include <algorithm> using namespace std; typedef long long LL; LL qmi ( int a, int b, int p) { LL res = 1 ; tandis que (b) { if (b & 1 ) res = res * a% p; b >> = 1 ; a = (LL) a * a% p; } return res; } int main () { int n; cin>> n; tandis que (n-- ) { int a, b, p; cin >> a >> b >> p; cout << qmi (a, b, p) << endl; } }
Si vous utilisez la violence, c'est O (n) = 10 ^ 9, et la puissance rapide est au niveau logn, log10 ^ 9 = 30;
Le principe est: par exemple, 4 ^ 5 = 4 ^ 2 ^ 0 + 4 ^ 2 ^ 2,
La première étape consiste à générer 4 ^ 2 ^ 0 = 4 mod 10;
La deuxième étape génère 4 ^ 2 ^ 1 = 6 mod 10;
La troisième étape consiste à donner naissance à 4 ^ 2 ^ 2 = 6 mod 10;
Vous pouvez voir que chaque pas est le carré du devant, donc le jeûne est le même. Au début, la base a = a, a = a * a = a ^ 2, a = a ^ 2 * a ^ 2 = a ^ 4, a = a ^ 4 * a ^ 4 = a ^ 8;
S'il y a 1, alors (a & 1) res = res * a; a >> = 1; a = a * a% p;
Remarque: J'oublierai toujours la condition si (a & 1). 4 ^ 101, res = 4, res = 4 * 4 ^ 4 = 4 ^ 5; l'exposant ressemble donc à une somme, mais lorsqu'il est ajouté au fond, il est continuellement carré et multiplié par le produit précédent.
res = 1; if (a & 1) res = res * a% p; a >> = 1; a = a * a;
Congruence inverse:
congruence a / b a * x mod m
b * x congruence 1 mod m
Théorème de Fermat: b et p sont relativement premiers, alors b ^ p-1 est congru p. (Par exemple 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 congruence p
Alors l'inverse multiplicatif de b% p est b ^ p-2. (Si le reste de b et p n'est pas 0, alors il ne doit pas y avoir d'élément inverse) (Si b et p sont relativement premiers, alors il doit y avoir un élément inverse b ^ (p-2) par le théorème de Fermat, car les deux nombres premiers sont> = 2.
Vous pouvez donc utiliser une alimentation rapide pour trouver:
#include <iostream> #include <algorithm> #include <cstdio> typedef long long LL; using namespace std; int qmi ( int a, int p, int k) { int res = 1 ; tandis 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); tandis 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 ( " impossible \ n " ); } }
int res = qmi (a, p-2 , p);
if (a% p) printf ("% d \ n" , res);
Notez que vous ne pouvez pas juger si le résultat renvoyé par res est 0 ou 1 car si un = 2, p = 2, il est égal à 1, donc cela dépend si a et p ne sont pas composites.