跳到主要内容
原文316 词数2 分钟

题解:P3846 【模板】BSGS / [TJOI2007] 可爱的质数

参考资料

题意简述

给定质数 pp 与整数 b,nb,n,求最小的非负整数 ll,使 bln(modp)b^l\equiv n\pmod p,无解则报告。

解题思路

m=pm=\lceil\sqrt p\rceilpp 为质数,b≢0b\not\equiv 0gcd(b,p)=1\gcd(b,p)=1,可用 BSGS(Baby-Step Giant-Step,大步小步)。

ll 写作 l=imjl=im-j0j<m0\le j<m),代入 blnb^l\equiv n 得:

bimnbj(modp)b^{im}\equiv n\cdot b^{j}\pmod p

两侧分别枚举:

  1. 小步:枚举 jj00m1m-1,将 nbjn\cdot b^{j} 连同 jj 存入哈希表;
  2. 大步:枚举 ii11mm,算出 bimb^{im} 查表,命中即得 l=imjl=im-j

若有解,最小解必小于 pm2p\le m^2,故枚举范围足以覆盖。ii 自小到大、哈希表对相同键保留较大的 jj,首个命中即最小的 lll=0l=0(即 n1n\equiv 1)单独特判。

时间复杂度为 O(p)O(\sqrt p)

参考代码

521 Bcpp
#include <bits/stdc++.h>
using namespace std;

using ll=long long;
ll bsgs(ll b,ll n,ll p)
{
if(n==1)return 0;
unordered_map<ll,ll> mp;
ll m=sqrt(p),k=n;
for(ll j=0;j<m;j++)
{
mp[k]=j;
k=k*b%p;
}
ll t=1;
for(ll i=0;i<m;i++)t=t*b%p;
k=1;
for(ll i=1;i<=m;i++)
{
k=k*t%p;
if(mp.count(k))return i*m-mp[k];
}
return -1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
ll p,b,n;
cin>>p>>b>>n;
ll res=bsgs(b,n,p);
if(res==-1)cout<<"no solution"<<'\n';
else cout<<res<<'\n';
return 0;
}