input:
2
3 2 1 1
1 1
2
5 4 3 2
1 4
4 3
2 100000
4
2
output:
1
2
1
题目大意:每组数据给出一个p代表国家数量,一个a,一个n代表目标旅行方案数,一个q代表询问个数,接下来n行每行给出一个s和d,s代表第i个目标旅行方案的初始国家,d代表第i个目标旅行方案的计划天数,假如当前所在城市为t,那么下一个所要去的城市就是(t*a)%p,对于每个询问,给出一个城市t,问n个目标旅行中有多少个目标会经过城市t。
解题思路:设当前询问经过的城市为x,当前所在点为st,对于每一个旅行方案分别判断st*a^j%p=x%p,0<=j<=d[i],对式子进行变形得到a^j%p=x*st^(-1)%p,这样我们可以先预处理出所有a^j%p,然后对于每个旅行方案求出temp=x*st^(-1)%p的值,但是我们怎么判断是否能在d[i]天之内到达x点呢?这就需要我们在预处理的时候记录一个mp[i],表示a^j%p=i的最小的j的值,也就是能到达点i所需要的最小天数,我们只需要判断temp<=mp[temp]即可。注意0没有逆元,所以当s[i]=0时要特别判断,即只有当询问的城市编号也是0的时候才会到达,否则永远不可能到达,这个题目的细节比较多,可以参考代码注意一下。
上代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <unordered_map>
using namespace std;
const int N=1010;
const int M=2e5+10;
long long pb[M],p,a,n,q,s[N],d[N],ni[N];
unordered_map<long long,int>mp;
long long ksm(long long a,long long b)
{
long long res=1;
while(b)
{
if(b&1)
res=res*a%p;
b>>=1;
a=a*a%p;
}
return res;
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
mp.clear();
cin>>p>>a>>n>>q;
pb[0]=1;
mp[1]=0;
for(int i=1;i<=n;i++)
cin>>s[i]>>d[i];
long long tmp=p;
for(int i=1;i<=M;i++)
{
pb[i]=1ll*pb[i-1]*a%p;
if(!mp.count(pb[i]))
mp[pb[i]]=i;
}
p=tmp;
for(int i=1;i<=n;i++)
ni[i]=ksm(s[i],p-2);
for(int i=1;i<=q;i++)
{
long long x;
cin>>x;
long long ans=0;
for(int j=1;j<=n;j++)
{
if(s[j]==0)
{
ans+=(x==s[j]);
continue;
}
long long temp=x*ni[j]%p;
if(mp.count(temp)&&mp[temp]<=d[j])
ans++;
}
cout<<ans<<endl;
}
}
return 0;
}