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
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
Each of the next qq lines contains one integer x_i(0\le x_i< P)xi(0≤xi
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
- #include
- #include
- #include
- #include
- #include
- #include
- #define int long long
- #define pii pair
- 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;
- }