题目链接
牛客多校 第五场
题目大意就是给出 x0,a,b,p,n, 求出一个数v在x的数列中最先出现的下标是多少
其中
x
i
=
a
∗
x
i
−
1
+
b
x_{i} = a*x_{i - 1} + b
xi=a∗xi−1+b
通过题目中给的式子 我们可以化简得到:
x
n
=
x
0
∗
a
n
+
b
∗
(
a
n
−
1
−
1
)
(
a
−
1
)
x_{n} = x_{0}*a^{n} + b*\frac{(a^{n - 1} - 1)}{(a - 1)}
xn=x0∗an+b∗(a−1)(an−1−1)
将v带入化简我们可以得到
a
n
=
v
∗
(
a
−
1
)
+
1
x
0
∗
(
a
−
1
)
+
b
a^{n} = \frac{v*(a - 1) + 1}{x0*(a - 1) + b}
an=x0∗(a−1)+bv∗(a−1)+1
根据BSGS 公式为
a
n
≡
b
(
m
o
d
m
)
a^{n}≡b\pmod{m}
an≡b(modm)
我们可将其化简为
(
a
t
)
i
≡
b
∗
a
j
(
m
o
d
m
)
(a^{t} )^{i}≡b*a^{j}\pmod{m}
(at)i≡b∗aj(modm)
具体得证明 可以去网上查一查,将其带入本题那么 式子就可以化简为
(
a
t
)
i
=
a
j
∗
v
∗
(
a
−
1
)
+
1
x
0
∗
(
a
−
1
)
+
b
⟺
(
a
t
)
i
∗
x
0
∗
(
a
−
1
)
+
b
v
∗
(
a
−
1
)
+
1
=
a
j
(a^{t} )^{i}= a^{j} *\frac{v*(a - 1) + 1}{x0*(a - 1) + b}\Longleftrightarrow(a^{t} )^{i}*\frac{x0*(a - 1) + b}{v*(a - 1) + 1} = a^{j}
(at)i=aj∗x0∗(a−1)+bv∗(a−1)+1⟺(at)i∗v∗(a−1)+1x0∗(a−1)+b=aj
带入我们枚举将其存起来,然后在枚举i一一查询找到返回即可,注意我们不能向平常一样t取
p
\sqrt{p}
p
这里应该取
p
∗
2
3
p*\frac{2}{3}
p∗32 即j的上界,i从0到
p
∗
1
3
p*\frac{1}{3}
p∗31
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,x0,a,b,p;
unordered_map<int ,int> mp;
int power(int a, int b,int mod){
int ans = 1;
while(b){
if(b&1){
ans = a*ans %mod;
}
b >>= 1;
a = a*a%mod;
}
return ans%mod;
}
int flag;
int t,t1;
void pre_BSGS(int a, int p){
mp.clear();
a %= p;
t = pow(p, 1.0/3.0) + 1;
t1 = pow(p, 2.0/3.0) + 1;
int val = 1;
for(int j = 0; j <= t1; j ++){
if(j == t1) flag = val;
mp[val] = j;
val = val*a%p;
}
}
int BSGS(int a, int b, int p){
for(int i = 1; i <= t; i ++){
b = b*flag%p;
if(mp.count(b))
{
return i*t1 - mp[b];
}
}
return -1;
}
signed main()
{
int t;
scanf("%lld",&t);
while(t --){
scanf("%lld%lld%lld%lld%lld",&n,&x0,&a,&b,&p);
pre_BSGS(a, p);
int q;
scanf("%lld",&q);
while(q --){
int v;
scanf("%lld",&v);
if(a == 1){
if(v == x0){
printf("0\n");
}
else{
int temp = (v - x0 + p) % p;
if(temp/b < n){
printf("%lld\n",temp/b);
}
else puts("-1");
}
}
else if(a == 0){
if(v == x0){
printf("0\n");
}
else if(b == v&&n >= 1){
printf("1\n");
}
else printf("-1\n");
}
else{
int temp = power(((v%p*(a - 1 + p)%p)%p+ b)%p,p-2,p) *((x0%p*(a - 1 + p)%p)%p + b)%p;
int ans = BSGS(a, temp, p);
if(ans < n) printf("%lld\n",ans);
else printf("-1\n");
}
}
}
}
/*
45
1000000000000000000 1 5 0 1000000007
5
1
10
1000000006
12345678
1234567*/