a x ≡ b ( m o d p ) a^x \equiv b \pmod p ax≡b(modp)
跟 BSGS 差不多,只是多了 p p p 可以不为质数这一条件。
首先你需要知道一个同余方程的性质:
给定一个同余式 a ≡ b ( m o d p ) a \equiv b\pmod p a≡b(modp)。
若存在 d d d 满足 d ∣ a , d ∣ b , d ∣ p d|a,d|b,d|p d∣a,d∣b,d∣p,那么则有 a d ≡ b d ( m o d p d ) \frac{a}{d} \equiv \frac{b}{d}\pmod{\frac{p}{d}} da≡db(moddp)。
那么这题就非常简单了。
我们令 d = gcd ( a , p ) d=\gcd(a,p) d=gcd(a,p),则可以将其转化为 a d × a x − 1 ≡ b d ( m o d p d ) \frac{a}{d} \times a^{x-1} \equiv \frac{b}{d} \pmod {\frac{p}{d}} da×ax−1≡db(moddp),一直重复直到 a a a 与 p p p 互质。
设执行了 c n t cnt cnt 次,那么则有 ( a d ) c n t × a x − c n t ≡ b d c n t ( m o d p d c n t ) (\frac{a}{d})^{cnt} \times a^{x-cnt} \equiv \frac{b}{d^{cnt}} \pmod {\frac{p}{d^{cnt}}} (da)cnt×ax−cnt≡dcntb(moddcntp)。就可以将其转化为 BSGS 来做了。
#include
#define IOS cin.tie(0),cout.tie(0),ios::sync_with_stdio(0)
#define mod 998244353
#define ll long long
#define db double
#define pb push_back
#define MS(x,y) memset(x,y,sizeof x)
using namespace std;
const int N=1e5+5,M=1e5+5;
const ll INF=1ll<<60;
void exgcd(ll a,ll b,ll &x,ll &y){
if(!b) x=1,y=0;
else exgcd(b,a%b,y,x),y-=a/b*x;
}
ll gcd(ll a,ll b){
if(!b) return a;
return gcd(b,a%b);
}
ll fpow(ll a,ll b,ll p){
ll ans=1;
for(;b;b>>=1){
if(b&1) ans=ans*a%p;
a=a*a%p;
}
return ans;
}
ll calc(ll a,ll p){
ll x=0,y=0;
exgcd(a,p,x,y);
x=(x%p+p)%p;
return x;
}
ll BSGS(ll g,ll a,ll p){
unordered_map<ll,ll> m;
a%=p;
// if(!g) return !a?1:-1;
ll B=(ll)sqrt(p)+1;
ll k=a,ng=calc(g,p),gB=1;
for(int i=0;i<B;i++){
if(!m[k]) m[k]=i+1;
k=k*ng%p;
gB=gB*g%p;
}
ll temp=1;
for(int i=0;i<=B;i++){
if(m[temp]) return (i*B%p+m[temp]-1)%p;
temp=temp*gB%p;
}
return -1;
}
ll exBSGS(ll a,ll b,ll p){
a%=p;b%=p;
ll cnt=0,d=gcd(a,p),tot=1;
while((d=gcd(a,p))^1){
if(tot==b) return cnt;
if(b%d) return -1;
cnt++;b/=d;p/=d;
tot=a/d*tot%p;
}
ll ntot=calc(tot,p);
b=b*ntot%p;
ll ans=BSGS(a,b,p);
if(ans!=-1) return ans+cnt;
return -1;
}
bool solve(){
ll a,b,p;
cin>>a>>p>>b;
if(!p) return 0;
ll ans=exBSGS(a,b,p);
if(ans==-1) cout<<"No Solution\n";
else cout<<ans<<"\n";
return 1;
}
int main(){
IOS;int T=1;
// cin>>T;
while(solve());
return 0;
}
注:
E N D \large{\mathbb{END}} END