http://poj.org/problem?id=3243
求A^x = B(mod C)中的x ,C是任意的数。
框架都在这里了:http://hi.baidu.com/aekdycoin/item/236937318413c680c2cf29d4
理解:http://blog.csdn.net/ivan_zjj/article/details/7597109
#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL long long
#define _LL __int64
#define eps 1e-12
#define PI acos(-1.0)
using namespace std;
const int maxn = 99991;
bool hash[maxn+10];
int idx[maxn+10];
LL val[maxn+10];
LL gcd(LL a, LL b)
{
if(b == 0)
return a;
return gcd(b,a%b);
}
void extend_gcd(LL a, LL b, LL &x, LL &y)
{
if(b == 0)
{
x = 1;
y = 0;
return;
}
extend_gcd(b,a%b,x,y);
LL t = x;
x = y;
y = t-a/b*y;
}
void insert(int id, LL vv)
{
LL v = vv%maxn;
while(hash[v] && val[v] != vv)
{
v++;
if(v == maxn)
v -= maxn;
}
if(hash[v] == false)
{
hash[v] = true;
idx[v] = id;
val[v] = vv;
}
}
int found(LL vv)
{
LL v = vv%maxn;
while(hash[v] && val[v] != vv)
{
v++;
if(v == maxn)
v -= maxn;
}
if(hash[v] == false)
return -1;
return idx[v];
}
LL baby_step(LL A, LL B, LL C)
{
memset(hash,false,sizeof(hash));
memset(idx,-1,sizeof(idx));
memset(val,-1,sizeof(val));
//首先特判log(C)以内的解。因为下面消因子法解出来的x >= b,但有可能x的解是小于b的。所以先特判。
LL ans = 1;
for(int i = 0; i <= 50; i++)
{
if(ans == B)
return i;
ans = ans*A%C;
}
//消因子,直到gcd(A,C) = 1,就可以用普通的baby_step
LL D = 1%C,tmp;
LL b = 0;
while((tmp = gcd(A,C)) != 1)
{
if(B%tmp)
return -1;
b++;
B = B/tmp;
C = C/tmp;
D = D*A/tmp%C;
}
LL M = ceil(sqrt(C*1.0));
LL k = 1;
for(int i = 0; i < M; i++)
{
insert(i,k);
k = k*A%C;
}
LL x,y;
for(int i = 0; i < M; i++)
{
extend_gcd(D,C,x,y);
x = x*B;
x = (x%C+C)%C;
int jj = found(x);
if(jj != -1)
return (LL)i*M+(LL)jj+b;
D = D*k%C;
}
return -1;
}
int main()
{
LL A,B,C;
while(~scanf("%lld %lld %lld",&A,&C,&B))
{
if(A == 0 && B == 0 && C == 0) break;
LL ans = baby_step(A,B,C);
if(ans == -1)
printf("No Solution\n");
else
printf("%lld\n",ans);
}
return 0;
}