Luogu4195 【模板】扩展BSGS
Luogu4195 【模板】扩展BSGS
\[a^x \equiv b (\bmod p)
\]
在\(a,p\)不互质情况下,我们无法直接进行\(BSGS\),原因是\(ac \equiv bc (\bmod p)\)无法直接推出\(a \equiv b (\bmod p)\)。
设\((a,p)=g\)。
当\(g \ne 1\)时。
假如\(g\)不整除\(b\),则无解,否则:
\[\frac{a}{g} a^{x-1} \equiv \frac{b}{g} (\bmod \frac{p}{g})\\
\]
递归求解即可,直到\((a,p)=1\),直接进行普通\(BSGS\)。
\(Code:\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
int a,p,b,c,k,orz;
int gcd(int x,int y)
{
if (!y)
return x;
return gcd(y,x%y);
}
int ksm(int x,int y)
{
int ans=1;
while (y)
{
if (y & 1)
ans=(ll)ans*x%p;
x=(ll)x*x%p;
y >>=1;
}
return ans;
}
void BSGS()
{
map<int,int>M;
int h=ceil(sqrt(p));
int z=b%p;
for (int i=0;i<h;++i)
{
M[z]=i;
z=(ll)z*a%p;
}
z=ksm(a,h);
int g=c;
for (int i=1;i<=h;++i)
{
g=(ll)g*z%p;
if (M.find(g)!=M.end())
{
printf("%d\n",i*h-M[g]+k);
return;
}
}
puts("No Solution");
}
void exBSGS()
{
if (b==1)
{
puts("0");
return;
}
c=1,k=0;
while ((orz=gcd(a,p))!=1)
{
if (b % orz)
{
puts("No Solution");
return;
}
++k,p/=orz,b/=orz,c=(ll)c*a/orz%p;
if (b==c)
{
printf("%d\n",k);
return;
}
}
BSGS();
}
int main()
{
while (scanf("%d%d%d",&a,&p,&b)!=EOF)
{
if (!(a | p | b))
return 0;
exBSGS();
}
return 0;
}