这道题目真是太坑爹了。。。狂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; }