luogu P3306 [SDOI2013] 随机数生成器
https://www.luogu.com.cn/problem/P3306
首先根据小学知识可以把原式子写成等比数列的形式
X
i
+
1
+
b
a
−
1
=
a
(
x
i
+
b
a
−
1
)
m
o
d
p
X_{i+1}+\frac{b}{a-1}=a(x_i+\frac{b}{a-1}) \mod p
Xi+1+a−1b=a(xi+a−1b)modp
所以
X
n
+
b
a
−
1
=
a
n
−
1
(
x
1
+
b
a
−
1
)
m
o
d
p
X_{n}+\frac{b}{a-1}=a^{n-1}(x_1+\frac{b}{a-1}) \mod p
Xn+a−1b=an−1(x1+a−1b)modp
a
n
−
1
=
.
.
.
.
m
o
d
p
a^{n-1}=....\mod p
an−1=....modp
这坨东西就可以大力BSGS了
注意一下边界就好了
code:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll mod;
ll qpow(ll x, ll y) {
ll ret = 1;
for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
return ret;
}
map<ll, ll> mp;
ll BSGS(ll a, ll b) {
int m = sqrt(mod + 1);
ll t = b % mod;
mp.clear();
for(int i = 0; i <= m; i ++, t = t * a % mod) mp[t] = i;
a = qpow(a, m); t = a;
if(!t) return b? -1 : 1;
for(int i = 1; i <= m + 1; i ++, t = t * a % mod) {
int j = mp.find(t) == mp.end()? -1 : mp[t];
if(j != -1) return 1ll * i * m - j;
}
return - 2;
}
int T;
ll s, t, a, b;
int main() {
scanf("%d", &T);
while(T --) {
scanf("%lld%lld%lld%lld%lld", &mod, &a, &b, &s, &t);
if(s == t) {puts("1"); continue;}
if(a == 0) {printf("%d\n", t == b? 2 : -1); continue;}
if(a == 1) {
if(! b) puts("-1");
else {
printf("%lld\n", (t - s + mod) % mod * qpow(b, mod - 2) % mod + 1);
}
continue;
}
ll y = b * qpow(a - 1, mod - 2) % mod;
t = (t + y) % mod, s = qpow(s + y, mod - 2);
printf("%lld\n", BSGS(a, t * s % mod) + 1);
}
return 0;
}