可以得出通项公式:
Xn=an−1×X1+b×∑i=0n−2ai
X
n
=
a
n
−
1
×
X
1
+
b
×
∑
i
=
0
n
−
2
a
i
∑n−2i=0ai ∑ i = 0 n − 2 a i 是一个等比数列和的形式,所以转化为:
Xn=an−1×X1+b×an−1−1a−1
X
n
=
a
n
−
1
×
X
1
+
b
×
a
n
−
1
−
1
a
−
1
所以就是要求最小的 n n 使得:
两边同时乘以 a(a−1) a ( a − 1 ) :
(a−1)×an×X1+a×b×(an−1−1)≡t×a×(a−1)(modp)
(
a
−
1
)
×
a
n
×
X
1
+
a
×
b
×
(
a
n
−
1
−
1
)
≡
t
×
a
×
(
a
−
1
)
(
mod
p
)
展开并移项:
an+1×X1−an×X1+an×b≡t×a×(a−1)+a×b(modp)
a
n
+
1
×
X
1
−
a
n
×
X
1
+
a
n
×
b
≡
t
×
a
×
(
a
−
1
)
+
a
×
b
(
mod
p
)
等号左边合并:
an×[(a−1)×X1+b]≡t×a×(a−1)+a×b(modp)
a
n
×
[
(
a
−
1
)
×
X
1
+
b
]
≡
t
×
a
×
(
a
−
1
)
+
a
×
b
(
mod
p
)
再移项( −1 − 1 为乘法逆元):
an≡[t×a×(a−1)+a×b]×[(a−1)×X1+b]−1(modp)
a
n
≡
[
t
×
a
×
(
a
−
1
)
+
a
×
b
]
×
[
(
a
−
1
)
×
X
1
+
b
]
−
1
(
mod
p
)
这样就是BSGS的模板了。
不过要特判三个情况:
(1) t=X1 t = X 1 :答案为 1 1 。
(2): t=X1 t = X 1 时答案为 1 1 ,时答案为 2 2 ,否则为。
(3) A=1 A = 1 : t=X1 t = X 1 时答案为 1 1 ,时答案为 −1 − 1 ,否则 X X <script type="math/tex" id="MathJax-Element-2181">X</script>是一个等差数列,直接利用逆元计算即可。
代码:
#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
inline int read() {
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
int MX, A, B, X1, t, S, C;
map<int, int> ha;
inline int qpow(int a, int b, const int &MX) {
int res = 1; while (b) b & 1 ? res = 1ll * res * a % MX : 0,
a = 1ll * a * a % MX, b >>= 1; return res;
}
inline int BSGS() {
int i, x = 1; for (i = 1; i <= S; ++i) {
x = 1ll * x * A % MX; if (!ha[x]) ha[x] = i;
}
int dalao = qpow(x, MX - 2, MX), tmp = C;
for (i = 0; i < S; ++i) {
if (ha[tmp]) {
int res = i * S + ha[tmp]; ha.clear(); return res;
}
tmp = 1ll * tmp * dalao % MX;
}
ha.clear(); return -1;
}
inline void work() {
MX = read(); A = read(); B = read(); X1 = read(); t = read();
if (t == X1) return (void) puts("1");
if (A == 0) {
if (t == X1) puts("1"); else if (t == B) puts("2");
else puts("-1"); return;
}
if (A == 1) {
if (B == 0) return (void) puts("-1");
int res = (t - X1 + MX) % MX;
res = 1ll * res * qpow(B, MX - 2, MX) % MX;
return (void) printf("%d\n", res + 1);
}
S = ceil(sqrt(MX)); int tmp = (A - 1 + MX) % MX;
C = (1ll * t * A % MX * tmp % MX + 1ll * A * B % MX) % MX;
C = 1ll * C * qpow((1ll * X1 * tmp % MX + B) % MX, MX - 2, MX) % MX;
printf("%d\n", BSGS());
}
int main() {
int T = read(); while (T--) work();
return 0;
}