题目
思路
先把exBSGS变成普通BSGS。
我们这样做:
a
x
≡
b
(
m
o
d
c
)
=
>
a
x
+
c
y
=
b
a^x\equiv b(\bmod~c)=>a^x+cy=b
ax≡b(mod c)=>ax+cy=b
接下来我们不停地除a,c的最大公约数(d1)。
b
1
=
a
d
1
a
x
−
1
+
c
1
y
b_1={a\over d_1}a^{x-1}+c_1y
b1=d1aax−1+c1y
我们接下来接着除gcd(a,c1)=d2
b
2
=
a
2
d
1
d
2
a
x
−
2
+
c
2
y
b_2={a^2\over d_1d_2}a^{x-2}+c_2y
b2=d1d2a2ax−2+c2y
我们不难发现此时若b不被gcd整除,则无解。
设一共做了
n
n
n次,
D
=
a
n
d
1
d
2
…
…
d
n
D={a^n\over d_1d_2……d_n}
D=d1d2……dnan
剩下的
a
x
−
n
≡
b
n
⋅
D
−
1
(
m
o
d
c
n
)
a^{x-n}\equiv b_n·D^{-1}(\bmod~c_n)
ax−n≡bn⋅D−1(mod cn)普通BSGS可解。
接下来考虑普通BSGS。
由指数模的周期性,得若有解,必有c以内的解。
我们考虑优(bi)美(tai)的分块。
分
n
\sqrt n
n块,那么每块就是
m
=
n
m=\sqrt n
m=n个数。
那么这时原式变成
a
i
m
−
j
≡
b
(
m
o
d
c
)
=
>
a
i
m
≡
a
j
b
(
m
o
d
c
)
a^{im-j}\equiv b(\bmod~c)=>a^{im}\equiv a^jb(\bmod~c)
aim−j≡b(mod c)=>aim≡ajb(mod c)
这里我们需要枚举
1
<
=
i
<
=
c
,
0
<
=
j
<
=
c
1<=i<=\sqrt c,0<=j<=\sqrt c
1<=i<=c,0<=j<=c
我们把右式存入hash表里(也可以map,只要数据水),这里一共
O
(
n
)
O(\sqrt n)
O(n)。
然后再枚举i,又
O
(
n
)
O(\sqrt n)
O(n)。
code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cmath>
#include<queue>
#include<deque>
using namespace std;
//When I wrote this code,God and I unterstood what was I doing
long long gcd(long long a,long long b)
{
long long r=a%b;
while (r)
{
a=b,b=r,r=a%b;
}
return b;
}
long long exgcd(long long a,long long b,long long &x,long long &y)
{
if (b==0)
{
x=1,y=0;
return a;
}
long long r=exgcd(b,a%b,y,x);
y-=(long long)(a/b)*x;
return r;
}
long long inv(long long a,long long m)
{
long long x,y;
exgcd(a,m,x,y);
return (x%m+m)%m;
}
struct fP{
long long tot,head[(((1<<16)-1)<<2)],nxt[500005],b[500005],v[500005],top,sck[500005];
void init()
{
tot=0;
while (top) head[sck[top--]]=0;
return;
}
void insert(long long x,long long y)
{
long long hask=x%(((1<<16)-1)<<2);
for (long long i=head[hask];i;i=nxt[i])
{
if (b[i]==x)
{
v[i]=y;
return;
}
}
if (!head[hask]) sck[++top]=hask;
nxt[++tot]=head[hask],head[hask]=tot;
b[tot]=x,v[tot]=y;
return;
}
long long QuantAsk(long long x)
{
long long hask=x%(((1<<16)-1)<<2);
for (long long i=head[hask];i;i=nxt[i])
{
if (b[i]==x) return v[i];
}
return -1;
}
} kyx;
long long BSGS(long long a,long long b,long long c)
{
if (b==1||c==1) return 0;
long long cnt=0,Gcd=gcd(a,c),d=1;
while (Gcd!=1)
{
if (b%Gcd!=0) return -1;
cnt++,b/=Gcd,c/=Gcd;
d=d*(a/Gcd)%c;
Gcd=gcd(a,c);
}
b=b*inv(d,c)%c;
kyx.init();
long long block=ceil(sqrt(c)),p=1;
for (long long i=0;i<block;i++)
{
if (p==b) return i+cnt;
kyx.insert(p*b%c,i);
p=p*a%c;
}
long long q=p,t;
for (long long i=block;i-block+1<=c-1;i+=block)
{
t=kyx.QuantAsk(q);
if (t!=-1) return i-t+cnt;
q=q*p%c;
}
return -1;
}
int main()
{
long long a,b,c;
while (1)
{
scanf("%lld%lld%lld",&a,&b,&c);
if (a==0&&b==0&&c==0) return 0;
a%=b,c%=b;
//if (check(a,b,c)) continue;
long long wj=BSGS(a,c,b);
if (wj==-1) puts("No Solution");
else printf("%lld\n",wj);
}
return 0;
}
//Now,only God know
//但行好事,莫问前程