题意:
告诉你B,N,P,让你求最小的L使得
题解:
BSGS模板,大致意思是将L变成ax+b的形式,定下x之后,式子就变成了这样:
B
b
=
=
N
B
−
a
x
(
m
o
d
P
)
B^b==NB^{-ax}(mod P)
Bb==NB−ax(modP)
那么我们只需要先枚举b(0<=b<=x),将所有值都记下来,再枚举a,同时查询即可。
这道题如果将x设为
P
\sqrt{P}
P的话会T,或许是我写的教丑,在经过一系列的尝试之后,确定x在2e3~3e3这个范围最优。
#include<stdio.h>
#include<iostream>
#include<map>
#include<math.h>
using namespace std;
#define ll long long
ll mod;
const ll inf=1e10;
ll qpow(ll a,ll b){ll ans=1;for(;b;b>>=1,a=a*a%mod)if(b&1)ans=ans*a%mod;return ans;}
map<ll,int>mp;
int main()
{
ll b,n;
while(scanf("%lld%lld%lld",&mod,&b,&n)!=EOF){
mp.clear();
int x=min(2500,(int)sqrt(mod)+1);
ll v=1;
ll ans=inf;
for(int i=0;i<=x;i++,v=v*b%mod){
if(mp.count(v))break;
mp[v]=i;
if(v==n)ans=min(ans,1ll*i);
}
v=n;
ll ret=qpow(b,x);
ret=qpow(ret,mod-2);
ll top=mod/x+1;
for(int i=0;i<=top;i++){
if(mp.count(v))ans=min(ans,1ll*i*x+mp[v]);
if(v==1&&i!=0)ans=min(ans,1ll*i*x);
if(i*x>=ans)break;
v=v*ret%mod;
}
if(ans==inf)printf("no solution\n");
else printf("%lld\n",ans);
}
return 0;
}