裸的bsgs
我们可以使用分块来优化暴力枚举,对于Ax≡B(mod C),我们可以令m=⌈⌉,x=i∗m+j,那么该式子就可以写成≡B(mod C),于是我们可以将进行预处理,表示达到这个值的指数项为多少,存到一个哈希表或者map里,之后我们只要枚举就行了,大致复杂度是O()。(知道了这个,这题就做完了qwq)
不知为何令x=i*m-j就过不了
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll g,p,n,A,B,m;
map<ll,ll>mp;
long long int qpow(ll x,ll y)
{
ll ans=1;
while(y)
{
if(y&1)
ans=ans*x%p;
x=x*x%p;
y>>=1;
}
return ans;
}
void intt()
{
ll x=1;
mp[1]=0;
for(ll j=1;j<=m;j++)
{
x=x*g%p;
if(!mp[x])
mp[x]=j;
}
}
//巧妙地求逆元
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b)
{
d=a,x=1,y=0;
}
else{
ex_gcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
ll inv(ll x)
{
ll d,xx,y;
ex_gcd(x,p,d,xx,y);
return d==1?(xx+p)%p:-1;
}
ll solve(ll x)
{
for(ll i=1;i<=m;i++)
{
ll v=x*inv(qpow(g,i*m))%p;
if(mp.count(v))
{
return i*m+mp[v];
}
}
return -1;
}
int main()
{
scanf("%lld%lld%lld",&g,&p,&n);
m=ceil(sqrt(p));
intt();
while(n--)
{
scanf("%lld%lld",&A,&B);
printf("%lld\n",qpow(B,solve(A)));
}
return 0;
}