http://www.cnblogs.com/wondove/p/8590582.html
这篇博客讲得挺好哒
当a与n互质时,a对于mod n才有逆元
1.欧拉公式 a ^ phi(p) = 1 (mod p) 要求a与p互质
2.扩展gcd
均可以解决逆元的问题
高次同余方程 A^x = B (mod p) 求x
1.A与p互质
m = [sqrt(p)] (分块)
令x = i * m + j
A ^ x = A ^ (i * m + j) = B (mod p)
A ^ j = B * A ^ ( -m * i ) (mod p) // j范围在(0,m),先预处理A ^ j , O( sqrt(p) )
再枚举i ,对于每个i,在A ^ j中找有没有和右边式子B * A ^ (- m * i) (mod p)相等的
(用二分的话 O (sqrt(p) * log p) 哈希大概就是O (sqrt (p) ) )
2.A与p不互质
d = gcd(A , p)
A ^ x = B (mod p) -> A ^ x - p * y = B
两边同除p
A' * A ^ (x - 1) - p' * y = B'
A' * A ^ (x - 1) = B' (mod p') 这样不断循环,将左边每次A‘乘起来,标记为D,直到A与p互质为止
并且如果B不整除d说明无解
num记录一共除d次数
D * A ^ (x - num) = B (mod p) A和p互质,可按传统方法计算
poj2417 (题目给的p是质数,所以不需要考虑A和p不互质的情况)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn =5e4;
typedef long long ll;
ll Aj[maxn];
struct node{
ll aj,j;
bool operator < (constnode & a)const{
return aj < a.aj || (aj == a.aj &&j< a.j);
}
}ns[maxn],t;
ll qk_pow(ll a,ll b,ll p)
{
ll ans = 1,k = a;
while (b) {
if(b & 1) ans = (ll)ans * k % p;
k = (ll)k * k % p;
b >>= 1;
}
return ans;
}
int main()
{
ll p,A,B;
while (scanf("%lld%lld%lld",&p,&A,&B) !=EOF) {
ll m = sqrt(0.5 + p);
Aj[0] =1;ns[0] =node{ 1,0};
for (ll i =1; i <= m; i ++) {
Aj[i] = Aj[i -1] * A % p;
ns[i] = node{ Aj[i],i};
}
sort(ns,ns + m +1);
ll ans = -1;
for (ll i =0; i <= m +2; i ++) {
ll ex = (-m * i % (p - 1) + p - 1) % (p - 1);
ll k = B * qk_pow(A,ex,p) % p;
t = node{k,0};
ll pos = lower_bound(