EXBSGS

#include <bits/stdc++.h>
#include <tr1/unordered_map>
using namespace std;
using std::tr1::unordered_map;
#define ll long long
const int maxn=1e6+7;
const int mod=998244353;
const int INF=0x3f3f3f3f;
/*
   BSGS算法  b^l==n%p  求解最小的l
   不妨直接把l拆分成i*m-j,这样的话同余方程就变为b^(i*m)==n*b^j%p
   直接枚举j属于[0,m) m=ceil///向上取整(sqrt(p)) map记录当前的j的数值
   随后枚举i属于[0,m)查询map是否存在j满足且需要满足i*m>j=op[s]
   很显然这只是gcd(b,p)=1的情况,此时枚举只到了m-2与费马小定理对应
   EXBSGS 由于gcd(p,b)不一定为1,所以我们可以求出gcd(p,b)根据裴蜀定理,有解的条件gcd(p,b)|n
   所以就一直求出gcd(d2=(p/d),b),一直到他们之间互质,期间如果gcd(p/d,b)!|n就是无解
   最后可以得到b^cnt/(d1*d2......*dcnt) *b^(l-cnt) == n/(d1*d2......*dcnt)mod(p/(d1*d2......*dcnt))
   (d1*d2......*dcnt)=D
   b^cnt/D * (b^(l-cnt))===n/Dmod(p/D)
   b^cnt/D和n/d互质所以一定有解,所以将原来的S=1ll改为b^cnt/D直接用BSGS求(b^(l-cnt))
   求得的x是l-cnt最后要加上cnt
*/
unordered_map<ll,ll>op;
ll p,b,n;
ll quick_pow(ll a,ll b,ll p)
{
   ll ans=1;
   while (b)
   {
    if (b&1)///b为奇数
        ans=(ans*a)%p;
     a=(a*a)%p;///b为偶数
     b>>=1;
   }
   return ans;
}
ll BSGS(ll p,ll b,ll n,ll ans)
{
    op.clear();
    ll m=ceil(sqrt(p));
    ll s=0;
    for (ll i=0,s=n;i<m;++i,s=s*1ll*b%p)///枚举的时候map记录位置
    {
        op[s]=i;
    }
    for (ll i=0,tmp=quick_pow(b,m,p),s=ans;i<m;++i,s=s*1ll*tmp%p )///查找j
    {
        if (op.find(s)!=op.end())
        {
            if (i*m>=op[s])return 1ll*i*m-op[s];
        }
    }
    return -1ll;
}

ll GCD(ll a,ll b){return b?GCD(b,a%b):a;}

ll EXBSGS(ll p,ll b,ll n)
{
    b%=p;
    n%=p;///先取模一下保证n,b<p
    if (n==1||p==1)return 0;///n==1 l==0 p==1 n%1==0  l任意取值,但要最小所以为0
    ll cnt=0;
    ll d=0;
    ll ans=1ll;
    while (d!=1)
    {
        d=GCD(b,p);
        if (n%d==1)return -1ll;///同余方程无解
        ++cnt;
        p/=d;
        n/=d;
        ans=(ans*1ll*b/d)%p;
        if (ans==n)return cnt;///特判情况 n*b^(l-cnt)==n/D mod(p/D) 此时的n*D==n%(p/d) 所以l==cnt
    }
    ll ret=BSGS(p,b,n,ans);
    if (ret==-1ll)return -1ll;
    else return ret+cnt;///求的是a^(x-cnt)
}

int main()
{
    while (EOF!=scanf("%lld%lld%lld",&b,&p,&n))///b^l==n%p
    {
        if (!b&&!p&&!n)return 0;
        ll cnt=EXBSGS(p,b,n);
        cnt==-1ll?cout<<"No Solution"<<endl:cout<<cnt<<endl;
    }
    return 0;
}

摘录自对该博客的理解

齐芒行,川锋明!
原文地址:https://www.cnblogs.com/qimang-311/p/13408448.html