BSGS简叙

#include <bits/stdc++.h>
using namespace std;
#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与费马小定理对应
*/
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 m=ceil(sqrt(p));
    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=1ll;i<m;++i,s=s*1ll*tmp%p )///查找j
    {
        if (op.find(s)!=op.end())
        {
            if (i*m>=op[s])return i*m-op[s];
        }
    }
    return -1ll;
}
int main()
{
    scanf("%lld%lld%lld",&p,&b,&n);///b^l==n%p
    ll cnt=BSGS(p,b,n);
    cnt==-1ll?cout<<"no solution"<<endl:cout<<cnt<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/qimang-311/p/13403294.html