一大堆边界一开始并不知道,胡乱判了几个之后一直WA
无奈之下只好去下载了数据,然后就疯狂判各种奇怪的边界了
刨去边界问题
首先我们考虑a=1的情况
x1+k*b=t(mod p)
ex_gcd即可解
考虑a>1的情况
令S=X+b/(a-1)
原式就变成了一个等比数列
即S1*a^k=(t+b/(a-1))(mod p)
移项之后BSGS解即可
其他边界都可以O(1)判断
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<map>
#include<cmath>
using namespace std;
typedef long long LL;
int T;
LL p,a,b,x1,x,y,d,t,inv;
map<LL,int>Q;
void ex_gcd(LL a,LL b,LL &d,LL &x,LL &y){
if(b==0){x=1;y=0;d=a;return;}
ex_gcd(b,a%b,d,y,x);y-=(a/b)*x;
}
LL pow_mod(LL v,LL b){
LL tmp=1;
while(b){
if(b&1)tmp=tmp*v%p;
v=v*v%p;b>>=1;
}return tmp;
}
LL log_mod(LL a,LL b,LL n){
if(a==0&&b==0)return 1;
if(a==0)return -1;
LL m=(int)(sqrt(n+0.5))+1;Q.clear();
LL v=pow_mod(a,m);v=pow_mod(v,n-2);
LL e=1;Q[1]=0;
for(int i=1;i<m;++i){
e=e*a%n;
if(!Q.count(e))Q[e]=i;
}
for(int i=0;i<m;++i){
if(Q.count(b))return i*m+Q[b]+1;
b=b*v%n;
}return -1;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&t);
if(x1==t){printf("1\n");continue;}
if(a==0){
if(b==t){printf("2\n");continue;}
else {printf("-1\n");continue;}
}
if(a==1){
if(b==0){printf("-1\n");continue;}
ex_gcd(b,p,d,x,y);
x1=(t-x1+p)%p;
if(x1%d!=0){printf("-1\n");continue;}
x=x*x1;
x=(x%p+p)%p;
printf("%lld\n",x+1);
continue;
}
inv=pow_mod(a-1,p-2);
b=b*inv%p;
x1=(x1+b)%p;t=(t+b)%p;
x1=pow_mod(x1,p-2);
t=t*x1%p;
printf("%lld\n",log_mod(a,t,p));
}return 0;
}