Description
Little Y finds there is a very interesting formula in mathematics:
XY mod Z = K
Given X, Y, Z, we all know how to figure out K fast. However, given X, Z, K, could you figure out Y fast?
【题目分析】
大题思路同poj2417,但是不一定是互质的。所以不能直接用拓展的欧几里得算法。需要消去同样的因子。
【代码】
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
const int maxn=99991;
using namespace std;
long long A,B,C;
bool hash[maxn];
long long idx[maxn],val[maxn];
inline void ins(long long id,long long vv)
{
long long v=vv%maxn;
while (hash[v]&&val[v]!=vv){v++; if(v==maxn) v=0;}
if (!hash[v]) hash[v]=1,val[v]=vv,idx[v]=id;
}
long long find(long long vv)
{
int v=vv%maxn;
while (hash[v]&&val[v]!=vv)
{v++;if (v==maxn) v=0;}
if (!hash[v]) return -1;
return idx[v];
}
void exgcd(long long a,long long b,long long &x,long long &y)
{
if (b==0) {x=1; y=0; return;}
exgcd(b,a%b,x,y);
long long t=x;
x=y; y=t-a/b*y;
}
long long gcd(long long a,long long b)
{while(a%b!=0) {long long c=a;a=b;b=c%b;} return b;}
long long bsgs(long long A,long long B,long long C){
long long ans=1;
for (long long i=0;i<=50;++i){
if (ans==B) return i;
ans=ans*A%C;
}
long long tmp,d=0,D=1%C;
while ((tmp=gcd(A,C))!=1){
if (B%tmp) return -1;
d++;
B/=tmp;
C/=tmp;
D=D*A/tmp%C;
}
memset(hash,0,sizeof hash);
memset(val,-1,sizeof val);
memset(idx,-1,sizeof idx);
long long rr=1;
long long m=ceil(sqrt(C*1.0));
for (int i=0;i<m;++i) {ins(i,rr);rr=rr*A%C;}
long long x,y;
for (int i=0;i<m;++i)
{
exgcd(D,C,x,y);
long long r=x*B%C;
r=(r%C+C)%C;
long long ans=find(r);
if (ans!=-1) return ans+i*m+d;
D=D*rr%C;
}
return -1;
}
int main()
{
while (scanf("%lld%lld%lld",&A,&C,&B)==3){
if (A+C+B==0) break;
long long res=bsgs(A,B,C);
if (res==-1) printf("No Solution\n");
else printf("%lld\n",res);
}
}