可以推出
当 a == 0 ; x0 等于 0 , 其余 xi 都等于 b ,
当 a == 1 ; , 是个等差数列,v = x0 + n * b ; n = (v - x0) / b
当 a >= 2 ; 是等比数列 ,所以
推出了的计算公式 , 就可以通过 BSGS算法求n,
BSGS算法是解方程 的一种算法, 首先通过费马小定理可以知道 x < p;
但是从在 [ 0, p ] 中枚举 x 也不行,会超时, 而这里就需要BSGS的巧妙构造 ,令 x = i * m - j; 则原式等于
预处理出,然后在查询时用O(m) 处理,用map查询是否存在 。
举个栗子: 就拿本题中m = 1000(虽然一般取m=sqrt(p)), 取 这样 i * 1000 可以取到 区间 [ 0, p] 的所有1000的倍数,现在要是 i * 1000 - j 能取到 [ 0, p] 内所有数, 那么只需 。
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
//https://ac.nowcoder.com/acm/contest/885/C
public class Cgenerator2 {
static int t, x0, a, b, p, q;
static long n;
static int N = (int)1e6+100;
static Map<Long , Integer> map = new HashMap<>();
static long qpow(long a, int x){
long res = 1;
while(x != 0){
if((x & 1) == 1) res = res * a % p;
a = a * a % p;
x /= 2;
}
return res;
}
static void init(){
long aa = qpow(a, 1000);
long x = 1;
for(int i = 1;i <= p/1000 + 1; i++){
x = x * aa % p;
if(map.get(x) == null)map.put(x, i);
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
t = in.nextInt();
while(t-- != 0){
map.clear();
n = in.nextLong(); x0 = in.nextInt(); a = in.nextInt();
b = in.nextInt(); p = in.nextInt(); q = in.nextInt();
init();
int v = 0;
long fm = qpow((b + (long)a * x0 % p - x0 + p) % p, p - 2);
while(q-- != 0){
v = in.nextInt();
if(a == 0){
if(v == x0) System.out.println("0");
else if(v == b) System.out.println("1");
else System.out.println("-1");
continue;
}
if(a == 1){
long ans = (v - x0 + p) * qpow(b, p - 2) % p;
if(ans < n) System.out.println(ans);
else System.out.println("-1");
continue;
}
long tmp = ( (long)v * (a - 1)%p + b) * fm % p;
int res = p + 1;
long val = tmp;
for(int i = 0; i <= 1000; i++){
if(map.get(val) != null){
res = Math.min((map.get(val) * 1000 - i)%p, res) ;
}
val = val * a % p;
}
if(res < n && res != p+1)
System.out.println(res);
else
System.out.println("-1");
}
}
}
}