now885C(BSGS+分块)

题目链接

https://ac.nowcoder.com/acm/contest/885/C?&headNav=acm

题意

给定 $n,x0,a,b,p$ ,$p$ 为质数,生成长度为 $n$ 的序列 $x_i=(ax{i-1}+b)\bmod p$ ,再给定 $m$ 次询问,问 $v$ 是否在数列中,并求出最早出现的下标

题解

这个序列可以求通项公式,有

上面涉及到除法。。所以需要特判分母为 $0$ 的地方,比较操蛋。。

然后这样就可以用 $BSGS$ 了,直接用显然是会 $T$ 的,然而底数是一样的,那么预处理可以一遍完成,考虑预处理规模 $x$ ,那么预处理复杂度为 $O(x)$ ,查询复杂度为 $O(q\frac{p}{x})$ ,那么取个均值复杂度就可以降到 $O(\sqrt{qp})$




代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
*         ┏┓    ┏┓
*         ┏┛┗━━━━━━━┛┗━━━┓
*         ┃       ┃  
*         ┃   ━    ┃
*         ┃ >   < ┃
*         ┃       ┃
*         ┃... ⌒ ...  ┃
*         ┃ ┃
*         ┗━┓ ┏━┛
*          ┃ ┃ Code is far away from bug with the animal protecting          
*          ┃ ┃ 神兽保佑,代码无bug
*          ┃ ┃           
*          ┃ ┃       
*          ┃ ┃
*          ┃ ┃           
*          ┃ ┗━━━┓
*          ┃ ┣┓
*          ┃ ┏┛
*          ┗┓┓┏━━━━━━━━┳┓┏┛
*           ┃┫┫ ┃┫┫
*           ┗┻┛ ┗┻┛
*/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<set>
#include<bitset>
#include<complex>
#include<cstdlib>
#include<assert.h>
#include<unordered_map>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define mid (x+y>>1)
#define sqr(x) ((x)*(x))
#define NM 1005
#define nm 2005
using namespace std;
const double pi=acos(-1);
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}



ll _n,_x,_a,_b,inf,cnt;
int m,n,ans[NM];
unordered_map<int,int>v;

ll qpow(ll x,ll t){
ll s=1;
for(;t;t>>=1,x=x*x%inf)if(t&1)s=s*x%inf;
return s;
}


int main(){
int _=read();while(_--){
_n=read();_x=read();_a=read();_b=read();inf=read();
_n=min(_n,inf);
m=read();n=sqrt(m*inf>>1);
if(_a==1){
if(_b>0){
while(m--){
ll t=(read()-_x+inf)%inf*qpow(_b,inf-2)%inf;
if(t<_n)printf("%lld\n",t);else printf("-1\n");
}
}else{
while(m--)if(read()==_x)printf("0\n");else printf("-1\n");
}
continue;
}
_b=_b*qpow(_a-1,inf-2)%inf;
_x+=_b;_x%=inf;_x=qpow(_x,inf-2);
if(_x==0){
_b=(inf-_b)%inf;
while(m--)if(read()==_b)printf("0\n");else printf("-1\n");
continue;
}
v.clear();
cnt=1;v[cnt]=0;
inc(i,1,n){
cnt=cnt*_a%inf;
if(!v.count(cnt))v[cnt]=i;else break;
}
cnt=qpow(cnt,inf-2);
inc(i,1,m){
ans[i]=_n;
for(int j=0,t=(_b+read())*_x%inf;j*n<inf;j++,t=1ll*t*cnt%inf)
if(v.count(t))ans[i]=min(ans[i],j*n+v[t]);
}
inc(i,1,m)if(ans[i]>=_n)printf("-1\n");else printf("%d\n",ans[i]);
}
return 0;
}