题目大意:给出A,B,C,求A^x=B(mod C)的最小x的值。
思路:著名的BSGS算法。将C拆分成根号块,先对一个根号内的东西暴力插入一个Hash表中(别问我为什么不用map,因为这个题卡map。。。
另我们要求的x=i * m + j,原式可以写成A^(i * m) * A^j = B(mod C)。这是ax=b(mod c)的形式我们只需要枚举i,然后看有没有符合要求的j就可以了。
CODE:
#define _CRT_SECURE_NO_WARNINGS
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
long long A,B,C;
void EXGCD(long long a,long long b,long long &d,long long &x,long long &y)
{
if(!b) {
d = a,x = 1,y = 0;
return ;
}
EXGCD(b,a % b,d,y,x);
y -= x * (a / b);
}
long long Solve(long long a,long long b,long long c) //ax = b(mod c)
{
long long x = 0,y = 0,d = 0;
EXGCD(a,c,d,x,y);
return ((x % c) + c) * b % c;
}
long long QuickPower(long long x,long long y)
{
long long re = 1;
while(y) {
if(y&1) re = re * x % C;
x = x * x % C;
y >>= 1;
}
return re;
}
struct HashSet{
#define MO 23333
int head[MO * 2 + 10],total;
int next[MO * 2 + 10],f[MO * 2 + 10];
long long val[MO * 2 + 10];
void Reset() {
memset(head,0,sizeof(head));
total = 0;
}
void Insert(long long x,int _) {
int temp = x % MO;
for(int i = head[temp]; i; i = next[i])
if(val[i] == x) {
f[i] = min(f[i],_);
return ;
}
next[++total] = head[temp];
val[total] = x;
f[total] = _;
head[temp] = total;
}
int Find(long long x) {
int temp = x % MO;
for(int i = head[temp]; i; i = next[i])
if(val[i] == x)
return f[i];
return -1;
}
}G;
int main()
{
while(scanf("%I64d%I64d%I64d",&C,&A,&B) != EOF) {
G.Reset();
long long temp = 1,m = ceil(sqrt((double)C));
for(int i = 0; i < m; ++i) {
G.Insert(temp,i);
temp = temp * A % C;
}
bool find = false;
for(int i = 0; i * m < C; ++i) {
long long temp = Solve(QuickPower(A,i * m),B,C);
if(G.Find(temp) != -1) {
printf("%I64d\n",i * m + G.Find(temp));
find = true;
break;
}
}
if(!find) puts("no solution");
}
return 0;
}POJ 2417 Discrete Logging Baby-Step-Gaint-Step
原文地址:http://blog.csdn.net/jiangyuze831/article/details/43953043