这题的是BSGS的裸题
BSGS
作用:用来求
a
n
≡
b
m
o
d
(
c
)
a^n≡b mod(c)
an≡bmod(c),给定
a
,
b
,
c
a,b,c
a,b,c求最小 的
n
n
n
要求:
a
与
c
互
质
a与c互质
a与c互质
由欧拉定理可知(ac互质)
a
m
≡
a
m
(
m
o
d
ϕ
(
c
)
)
m
o
d
(
c
)
a^{m}≡a^{m (mod\phi(c))} mod(c)
am≡am(modϕ(c))mod(c)
因为
ϕ
(
c
)
<
c
\phi(c)<c
ϕ(c)<c,所以只要
n
n
n在(0,c)中无解,则一定无解。
一种暴力算法
令
n
=
i
∗
t
−
j
n=i*t-j
n=i∗t−j,
则
a
i
t
≡
b
⋅
a
j
(
m
o
d
(
c
)
)
a^{it}≡b\cdot a^j(mod(c) )
ait≡b⋅aj(mod(c))
暴力枚举
i
=
0
,
1
,
2
,
⋯
c
t
+
1
,
j
=
0
,
1
,
⋯
t
i=0,1,2,\cdots\frac{c}{t}+1,j=0,1,\cdots t
i=0,1,2,⋯tc+1,j=0,1,⋯t
然后同余的组即是一组解,在选出最小的即可,该复杂度是
O
(
t
+
c
t
)
O(\sqrt{t+\frac{c}{t}})
O(t+tc)
先暴力
j
j
j,再暴力
i
i
i,显然
i
i
i越小,
n
n
n就越小,所以找到第一个
i
i
i,就找到了最小解。
当求少数解时,令
t
=
n
t=\sqrt{n}
t=n 时间复杂度最优,当但
a
a
a相同,求多组
b
b
b下的解时,要适当调整t的值,并预处理式子左边的值。详见代码。
ac代码
//#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
#include<map>
#define ll long long
#define endl '\n'
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
const int MX=4e2+7;
const int mod=8191;
using namespace std;
int p[MX],k[MX];
const int m=2;
ll qpow(ll a,ll b,ll MOD=mod){for(ll ans=1;;a=a*a%MOD,b>>=1){if(b&1)ans=ans*a%MOD;if(!b)return ans;}}
ll inv(ll a,ll MOD=mod){return qpow(a,MOD-2,MOD);}
ll __gcd(ll a,ll b){return a*b/__gcd(a,b);}
ll fmul(ll a, ll b, ll mod) {
ll d = (ll)double(a * (long double)b / mod + 0.5);
ll ret = (a * b - d * mod) % mod;
if (ret < 0) {
ret += mod;
}
return ret;
}
ll bsgs(ll a, ll b, ll c, ll q = 1) {
map<ll, int> x;
ll m = ceil(sqrt(c)) + 1;
ll v = 1;
for(int i = 0; i < m; i++) {
x[v*b%c] = i;
v=v*a%c;
}//暴力存所有b*a^j,并记录位置
for(int i = 1; i <= m; i++) {
q=q*v%c;//暴力所有a^it,并查是否有同余的
//map<ll,ll> ::iterator it = x.find(q);
if(x[q]) {
return i * m - x[q];
}
}
return -1;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
ll P,B,N;
while(cin>>P>>B>>N)
{
if(N==1)cout<<0<<endl;
else{
ll t=bsgs(B,N,P);
if(t==-1)cout<<"no solution\n";
else cout<<t<<endl;
}
}
}