Clever Y
Description
小Y发现,数学中有一个很有趣的式子:
XY mod Z = K
给出
X
、
但是如果给出
X
、
Input
本题由多组数据(不超过20组),每组测试数据包含一行三个整数
X
、
Output
对于每组数据:如果无解则输出一行
Sample Input
5 58 33
2 4 3
0 0 0
Sample Output
9
No Solution
Solution
扩展 Baby-Step-Giant-Step 模板题。
Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define LL long long
#define HASH_MOD 786433
using namespace std;
LL x,z,k,cnt=0,xxx,yyy,ans;
LL ex_gcd(LL x,LL y,LL &a,LL &b){
if(y==0){a=1;b=0;return x;}
LL fa,fb;
LL c=ex_gcd(y,x%y,fa,fb);
a=fb;
b=fa-fb*(x/y);
return c;
}
struct map{
LL h[800000],v[800000],nxt[800000],ne[800000];
void clear(){
memset(nxt,-1,sizeof nxt);
memset(h,-1,sizeof h);
ne[786433]=0;
for(LL i=0;i<786433;i++)ne[i]=i;
}
LL fi(LL x){
LL tmp=x,pre;
while(tmp!=ne[tmp])tmp=ne[tmp];
while(x!=tmp){pre=ne[x];ne[x]=tmp;x=pre;}
return tmp;
}
void insert(LL x,LL y){
LL mx=x%HASH_MOD;
while(nxt[mx]!=-1)
mx=nxt[mx];
nxt[mx]=fi(0);
ne[nxt[mx]]=ne[nxt[mx]]+1;
h[nxt[mx]]=x;
v[nxt[mx]]=y;
}
LL find(LL x){
LL mx=x%HASH_MOD;
while(x!=h[mx]&&nxt[mx]!=-1)mx=nxt[mx];
if(x!=h[mx])return -1;
return v[mx];
}
};
map hash;
int main(){
while(scanf("%lld%lld%lld",&x,&z,&k)!=EOF&&(x||z||k)){
hash.clear();
LL gg=ex_gcd(x,z,xxx,yyy),d=1,MAXN,tmp,tmp2,tt;
while(gg!=1){
if(k%gg!=0){printf("No Solution\n");goto nxt;}
k/=gg;z/=gg;d*=x/gg;
cnt++;
gg=ex_gcd(x,z,xxx,yyy);
}
x%=z;k%=z;
MAXN=ceil(sqrt((double)z)),tmp=1;
if(k==d%z){printf("0\n");goto nxt;}
hash.insert(1,0);
for(LL i=1;i<MAXN;i++){
tmp=tmp*x%z;
if(d*tmp%z==k){
if(i<=cnt){printf("%lld\n",i);goto nxt;}
else{printf("%lld\n",i+cnt);goto nxt;}
}
hash.insert(tmp,i);
}
tmp2=tmp,tt=tmp*x%z;
for(LL i=MAXN;i<=cnt;i++){
tmp2=tmp2*x%z;
if(d*tmp%z==k){printf("%lld\n",i);goto nxt;}
}
tmp=tt;
if(d*tmp%z==k){
if(MAXN<=cnt){printf("%lld\n",MAXN);goto nxt;}
else{printf("%lld\n",MAXN+cnt);goto nxt;}
}
ex_gcd(d*tmp,z,xxx,yyy);
xxx=(xxx*k%z+z)%z;
if((ans=hash.find(xxx))!=-1){printf("%lld\n",ans+MAXN+cnt);goto nxt;}
for(LL i=2;i<=MAXN;i++){
tmp=tmp*tt%z;
ex_gcd(d*tmp,z,xxx,yyy);
xxx=(xxx*k%z+z)%z;
if((ans=hash.find(xxx))!=-1){printf("%lld\n",ans+MAXN*i+cnt);goto nxt;}
}
printf("No Solution\n");
nxt:;
}
return 0;
}