快速幂+同余方程+BSGS
同余方程在解的时候要注意,在将exgcd求出的解变换为原方程的解的时候,要取模
BSGS的原理就是用分块+hash优化暴力,要注意特判 a 和 b 是 p 的倍数的时候.
对于预处理,要预处理出来, $0 sim t $的Hash值,以处理 答案是 0 的情况
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
#define ll long long
using namespace std;
ll p, a, b, n, opt;
ll quick_mod(ll n, ll k, ll p) {
ll ans = 1;
while(k) {
if(k & 1ll) (ans *= n) %= p;
(n *= n) %= p;
k >>= 1;
}
return ans;
}
ll exgcd(ll a, ll b, ll &x, ll &y) {
if(!b) {
x = 1; y = 0;
return a;
}
ll t = exgcd(b, a % b, x, y);
ll k = y;
y = x - a / b * y;
x = k;
return t;
}
void work2() {
ll r1, r2;
ll t = exgcd(a, p, r1, r2);
if(b % t) {printf("Orz, I cannot find x!
");return;}
r1 *= b / t;
r1 %= (p / t);
(r1 += (p / t)) %= (p / t);
printf("%lld
", r1);
}
void BSGS() {
b %= p;
if(a % p == 0) {
if(b == 1) {printf("0
");return;}
if(!b) {printf("1
");return;}
printf("Orz, I cannot find x!
");
return;
}
map <int, int> Hash;
Hash.clear();
ll t = ceil(sqrt(p)), k = 1ll;
for(int i = 0; i <= t; i++) {
Hash[b * k % p] = i;
(k *= a) %= p;
}
ll tmp = quick_mod(a, t, p), ans = tmp;
for(int i = 1; i <= t; i++) {
if(Hash.find(ans) != Hash.end()){
printf("%lld
", i * t - Hash[ans]);
return;
}
(ans *= tmp) %= p;
}
printf("Orz, I cannot find x!
");
}
int main() {
cin >> n >> opt;
for(int i = 1; i <= n; i++) {
cin >> a >> b >> p;
switch(opt) {
case 1 : printf("%lld
", quick_mod(a, b, p));break;
case 2 : work2();break;
case 3 : BSGS();break;
}
}
return 0;
}