Problem Description
As a cold-blooded, hot-blooded, and iron-blooded vampire, Shinobu loves traveling around.
There are PP countries in total, numbered 0,1,\dots ,P-10,1,…,P−1.(It is guaranteed that PP is a prime number)
It is known that when Shinobu is in the country numbered ii, the next country she visits must be the country numbered (i\cdot a) \mod P(i⋅a)modP (aa is a constant parameter), and it takes Shinobu 11 day to go from one country to another.
In order to travel smoothly, Shinobu has customized nn travel plans, and the ii-th travel plan is represented by the starting country s_isi and the travel days d_idi.
For example, if P = 233,\ a = 2P=233, a=2, a plan's starting country is 11 and travel days is 22, then Shinobu will visit the city { 1,2,4 }1,2,4 according to this plan.
Playf knows these travel plans and the value of parameter aa, now he wants to ask you qq questions. The ii-th question asks how many travel plans will make shinobu visit the country x_ixi.
Input
The first line of the input contains one integer TT ((1\leq T\leq 51≤T≤5 )) --- the number of test cases. Then TT test cases follow.
For each testcase, the first line contains four integers P,\ a,\ n,\ q(2\le a< P \le 1000000007, 1\le n \le 1000, 1\le q \le 1000 )P, a, n, q(2≤a<P≤1000000007,1≤n≤1000,1≤q≤1000) --- the number of countries, the value of aa, the number of Shinobu's travel plans and the number of playf's questions.
Each of the next nn lines contains two integers s_i,\ d_i(0\le s_i< P, 1\le d_i \le 200000 )si, di(0≤si<P,1≤di≤200000) --- the starting country and the travel days.
Each of the next qq lines contains one integer x_i(0\le x_i< P)xi(0≤xi<P) --- playf's questions.
It is guaranteed that PP is a prime number.
Output
For each testcase, print qq lines, the ii-th line contains one integer --- the answer to the ii-th question.
Sample Input
2
3 2 1 1
1 1
2
5 4 3 2
1 4
4 3
2 100000
4
2
Sample Output
1
2
1
题意: 每组数据给出P,a,n,q,接着给出n条旅游计划,每个旅游计划包含起点si以及持续时间di,然后是q次询问,每次询问给出目标地点xi,对于每次询问输出有多少路线经过目标地点xi,已知每天会从当前地点i移动至地点i*a%P,P是质数。
分析: 对于每个目标地点都遍历一遍所有计划,然后根据题意写出下面这个方程,s*a^y 同余 xi(Mod P) ,实际上这个计划能否经过xi等价于上式中最小解y是否小于等于d,对公式进行变形,两侧同时乘s逆元,就变成了a^y 同余 s^-1*xi(Mop P),可以维护出来a^y在y∈[1, 200000]范围内所有的值,并存放在一个map中,这样就可以通过该值查找到最小的y了,之后在遍历的时候只需要看一下map[s^-1*xi]是否存在,如果存在再看下值是否小于等于d,满足的话就说明这个计划会经过xi。最后需要注意求s逆元的过程不能放在q*n的二层循环中,虽然只是多一个log,但hduoj跑的比较慢,这样是会TLE的,正确做法应该是把各个s的逆元提前预处理出来。
具体代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <unordered_map>
#define int long long
#define pii pair<int, int>
using namespace std;
//s*a^x == t(Mod P)
//a^x == s^-1*t(Mod P)是否存在x <= d的解
int P, a, n, q;
int A[200005];
pii p[1005];
int inv[1005];
unordered_map<int, int> mp;
int ksm(int base, int power){
int ans = 1;
while(power){
if(power&1) ans = ans*base%P;
base = base*base%P;
power >>= 1;
}
return ans;
}
signed main()
{
A[0] = 1;
int T;
cin >> T;
while(T--){
mp.clear();
scanf("%lld%lld%lld%lld", &P, &a, &n, &q);
for(int i = 1; i <= 200000; i++){
A[i] = (A[i-1]*a)%P;
if(mp.count(A[i])) continue;
mp[A[i]] = i;
}
mp[1] = 0;
for(int i = 1; i <= n; i++){
scanf("%lld%lld", &p[i].first, &p[i].second);
inv[i] = ksm(p[i].first, P-2);
}
for(int i = 1; i <= q; i++){
int ans = 0;
int t;
scanf("%lld", &t);
for(int j = 1; j <= n; j++){
if(p[j].first == 0 && t == 0){
ans++;
continue;
}
if(!mp.count(inv[j]*t%P)) continue;
if(mp[inv[j]*t%P] <= p[j].second) ans++;
}
printf("%lld\n", ans);
}
}
return 0;
}