可以得出通项公式:
Xn=an−1×X1+b×∑i=0n−2aiXn=an−1×X1+b×∑i=0n−2ai
∑n−2i=0ai∑i=0n−2ai是一个等比数列和的形式,所以转化为:
Xn=an−1×X1+b×an−1−1a−1Xn=an−1×X1+b×an−1−1a−1
所以就是要求最小的nn使得:
两边同时乘以a(a−1)a(a−1):
(a−1)×an×X1+a×b×(an−1−1)≡t×a×(a−1)(modp)(a−1)×an×X1+a×b×(an−1−1)≡t×a×(a−1)(modp)
展开并移项:
an+1×X1−an×X1+an×b≡t×a×(a−1)+a×b(modp)an+1×X1−an×X1+an×b≡t×a×(a−1)+a×b(modp)
等号左边合并:
an×[(a−1)×X1+b]≡t×a×(a−1)+a×b(modp)an×[(a−1)×X1+b]≡t×a×(a−1)+a×b(modp)
再移项(−1−1为乘法逆元):
an≡[t×a×(a−1)+a×b]×[(a−1)×X1+b]−1(modp)an≡[t×a×(a−1)+a×b]×[(a−1)×X1+b]−1(modp)
这样就是BSGS的模板了。
不过要特判三个情况:
(1)t=X1t=X1:答案为11。
(2):t=X1t=X1时答案为11,时答案为22,否则为。
(3)A=1A=1:t=X1t=X1时答案为11,时答案为−1−1,否则XX是一个等差数列,直接利用逆元计算即可。
代码:
#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;
}