2019牛客暑期多校训练(第五场)C-generator 2
2019牛客暑期多校训练(第五场)C-generator 2
题目描述
There is a sequence of length n:x0,x1,x2,…,xn−1. Please answer Q queries. Each query consists of one integer v, asking the minimum index i such that xi=v. If the sequence doesn’t have any number with value v, you only need to output -1.
Does the problem look simple? Surprise! The value of n may be as large as 1018!
Because n is so large. We will only give you four integers x0,a,b,p to generate the sequence. For all i>0, the sequence is generated as xi=(a⋅xi−1+b)mod p.
输入描述:
The first line of input contains an integer T (T≤4) denoting there are T tests in the input.
Each test contains Q+2 lines.
The first line of each test contains five integers n,x 0,a,b,p (1≤n≤1018,0≤xp,a,b<p≤109+9, p is a prime number).
The second line contains one integer Q (Q≤1000).
Each of the following Q lines contains one integer v (0≤v<p).
输出描述:
For each query, print one integer as the answer in one line.
示例1
输入
3
1000000009 1 1 1 1000000009
5
0
1
10
1000000008
1000000007
100000009 1 1 1 1000000009
3
0
10
1000000008
1000000000000000000 1 5 0 1000000007
6
0
1
10
1000000006
12345678
1234567
输出
1000000008
0
9
1000000007
1000000006
-1
9
-1
-1
0
381838283
500000003
652614354
581802189
说明
For the first test, the sequence looks like 1, 2, 3, …, 1000000008, 0. So the position of the first occurrence of value v is v - 1 except for value 0 which occurs at 1000000008.
示例2
输入
2
1000000000000000000 5 2 2 1000000007
4
0
1
2
3
5 1 0 3 950000017
4
0
1
2
3
输出
115068150
342074
115068151
-1
-1
0
-1
1
题意
已知x[i]=(a*x[i-1]+b)%p,求满足等式的x数组的下标,且该下标小于n。若不存在则输出-1。
思路
BSGS算法(北上广深算法,拔山盖世算法 )。
首先,我们可以根据递推式求出x
关于x[0]的表达式。
然后。。。然后。。。然后。。。
就没有然后了。
发现是一个BSGS的式子。
求就完了。
坑点
真特么多。
首先,这题时间卡的很紧,如果用map哈希的话很容易超时,所以我后来用了unordered_map。
然后,我队友用链式前向星手写哈希跑了627ms,tql。
大佬的CSDN个人主页
之后还加了很多小优化,具体的就看BSGS和initBSGS函数部分的代码吧。
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+5; ll quickpow(ll a,ll b,ll mod) { ll ans=1; while(b) { if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans; } unordered_map<int,int> M; ll up,down,mul; void initBSGS(ll y,ll p) { M.clear(); up=ceil(pow(p,2.0/3)); down=ceil(pow(p,1.0/3)); ll num=1; for(int i=0; i<=up; i++) { if(i==up) mul=num; M[num]=i; num=num*y%p; } } ll BSGS(ll y,ll z,ll p) { ll num=quickpow(z,p-2,p); for(int i=1; i<=down+1; i++) { num=num*mul%p; if(M.count(num)) return i*up-M[num]; } return -1; } int main() { int T; scanf("%d",&T); while(T--) { ll n,x0,a,b,q,v,mod; scanf("%lld%lld%lld%lld%lld",&n,&x0,&a,&b,&mod); initBSGS(a,mod); scanf("%lld",&q); while(q--) { scanf("%lld",&v); if(a==0) { if(v==x0) printf("0\n"); else if(v==b&&n>=1) printf("1\n"); else printf("-1\n"); } else if(a==1) { if(b==0) printf("%d\n",v==x0?0:-1); else { int invb=quickpow(b,mod-2,mod); v=((v-x0+mod)%mod)*invb%mod; printf("%d\n",v<n?v:-1); } } else { if(x0==0&&b==0) printf("%d\n",v==0?0:-1); else { ll num=quickpow((((1-a+mod)%mod)*x0%mod-b+mod)%mod,mod-2,mod)*((((1-a+mod)%mod)*v%mod-b+mod)%mod)%mod; ll ans=BSGS(a,num,mod); if(ans<n) printf("%lld\n",ans); else printf("-1\n"); } } } } return 0; }
- 2019牛客暑期多校训练营(第五场)C generator 2 —— BSGS
- 2019牛客暑期多校训练营 第五场
- 2019牛客暑期多校训练营(第五场)H subsequence 2(拓扑排序)
- 2019牛客暑期多校训练营(第五场)G(DP)
- 2019牛客暑期多校训练(第七场)H-Pair
- 2019牛客暑期多校训练(第八场)D-Distance
- 2019牛客暑期多校训练(第九场)J-Symmetrical Painting
- 2019牛客暑期多校训练营(第五场)A digits
- 2019牛客暑期多校训练营(第一场)
- 2019牛客暑期多校训练营(第一场)J:Fraction Comparision
- 2019牛客暑期多校训练营 第二场
- 2019牛客暑期多校训练营(第四场)I string —— 后缀自动机+回文自动机
- 2019暑期训练-牛客第四场
- 2019牛客暑期多校训练营(第四场)D triples I
- 2019牛客暑期多校训练营(第六场)J(枚举)
- 2019牛客暑期多校训练营(第七场) B Irreducible Polynomial
- 2019牛客暑期多校训练营(第七场)H(数位DP)
- 2019牛客暑期多校训练营(第一场)A-Equivalent Prefixes
- 2013暑期多校联合训练\第五场 Problem F Magic Pen 6
- 2019牛客暑期多校训练营(第七场)D Number