xn=axn−1+b
设
xn−k=a(xn−1−k)
解得
k=b1−a
即
xn−k=(x1−k)×an−1
将k代入,整理式子
问题转变为求最小的n满足等式
(1−a)xn−b=((1−a)x1−b)an−1
此时用BSGS求解即可:
令
m=⌈p√⌉
A=(1−a)xn−b
B=(1−a)x1−b
即求
A≡Ban−1(mod p)
Aaj≡Bamj
枚举左边和右边,判断相等的情况即可
特殊情况:a = 1(用扩展欧几里得算法求逆元) , b = 1(特判)
一个地方没有取模调了一晚上gg
#include <cassert>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define INF ( 1LL << 62 )
#define N 1000050
#define eps 0.0000001
using namespace std;
typedef long long LL;
struct Monster{ LL u,l; }lzk[N];
LL lhr[N],p,a,b,x,t,A,B,am;
LL m;
inline LL read() {
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&& ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
LL ex_gcd(LL a,LL b,LL &x,LL &y) {
if (b == 0) { x = 1; y = 0; return a; }
LL q = ex_gcd(b,a%b,y,x);
y -= (a / b) * x;
return q;
}
bool cmp(Monster p1,Monster p2) {
return p1.u == p2.u ? p1.l > p2.l : p1.u < p2.u;
}
int main()
{
int T = read();
while (T--) {
p = read() , a = read() , b = read() , x = read() , t = read();
if (t >= p || x >= p) assert(0);
if (x == t) {
printf("1\n"); continue;
}
if(a==0) {
if(b == t) printf("2\n"); else printf("-1\n");
continue;
}
if ( a == 1 ) {
LL db,dp;
LL lhr = ex_gcd(b,p,db,dp);
LL C = (t - x + p) % p;
if (C % lhr) {
printf("-1\n"); continue;
}
C /= lhr;
db = db * C % p;
while (db < 0) db += p;
printf("%lld\n",db+1);
continue;
}
A = (1LL - a) * t - b;
B = (1LL - a) * x - b;
m = ceil( sqrt(p) ) + eps;
A %= p; B %= p;
while (A < 0) A += p;
while (B < 0) B += p;
lzk[0].u = A;
for (int j=1;j<=m;j++) {
lzk[j].u = ( lzk[j-1].u * a ) % p;
lzk[j].l = j;
}
sort(lzk+1,lzk+m+1,cmp);
lhr[0] = B; am = 1LL;
for (int i=1;i<=m;i++) am = ( am * a ) % p;
for (int i=1;i<=m;i++) lhr[i] = ( lhr[i-1] * am ) % p;
LL ans = INF;
for (LL i=1;i<=m;i++) {
int l = 1 , r = m;
while (l < r) {
int mid = (l + r) >> 1;
if (lzk[mid].u >= lhr[i]) r = mid; else l = mid + 1;
}
if (lzk[l].u == lhr[i])
ans = min(ans,i * m - lzk[l].l);
}
if (ans == INF) printf("-1\n"); else printf("%lld\n",ans+1);
}
return 0;
}