[推公式]Shinobu loves trip 2022杭电多校第6场 1007

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

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值