这道题目真是太坑爹了。。。狂Wa无数次。
将原来那个看成X0,最后答案再加1,这样会简单一点,假设答案是n(最后需要+1),那么不断迭代会发现
Xn=A^nX0+(A^n-1+A^n-2+...+1)B≡t(mod p),然后运用等比数列公式得到A^nX0+(A^n-1)/(A-1) *B≡t(mod p),两边同乘(A-1),移项得到:
[(a-1)*X0+b] A^n≡t(a-1)+b(mod p),然后就可以运用逆把 A^n求出来,然后就可以运用BSGS(Baby-Step-Giant-Step,Shank大步小步法)得到n了。
注意上述公式再a=0,a=1时失效,需要特判。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
int p,a,b,x,t,n,cnt; struct node{ int x,y; }c[100005];
int inv(int x){
int i,sum=1;
for (i=p-2; i; i>>=1,x=(ll)x*x%p) if (i&1) sum=(ll)sum*x%p;
return sum;
}
bool cmp(node aa,node bb){ return (aa.x==bb.x)?aa.y<bb.y:aa.x<bb.x; }
int find(int v){
int l=1,r=n,mid;
while (l<r){
mid=(l+r)>>1; if (c[mid].x<v) l=mid+1; else r=mid;
}
return (c[l].x==v)?c[l].y:-1;
}
int bsgs(int u,int v){
int i,tmp=1; n=(int)sqrt(p)+1;
c[1].x=1; c[1].y=1;
for (i=2; i<=n; i++){ c[i].x=(ll)c[i-1].x*u%p; c[i].y=i; }
tmp=inv((ll)c[n].x*u%p);
sort(c+1,c+n+1,cmp);
for (i=0; i<n; i++){
int k=find(v); if (k!=-1) return i*n+k;
v=(ll)v*tmp%p;
}
return -1;
}
int solve(){
if (x==t) return 1;
if (!a) return (b==t)?2:-1;
if (a==1) return (b)?(ll)inv(b)*(t-x+p)%p+1:-1;
int fz=((ll)t*(a-1)%p+b)%p,fm=((ll)x*(a-1)%p+b)%p;
return bsgs(a,(ll)fz*inv(fm)%p);
}
int main(){
int cas; scanf("%d",&cas);
while (cas--){
scanf("%d%d%d%d%d",&p,&a,&b,&x,&t);
printf("%d\n",solve());
}
return 0;
}
by lych
2016.2.15