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;
}
posted @ 2021-02-07 10:09  GK0328  阅读(39)  评论(0编辑  收藏  举报