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 d,x1,y1;
d=exgcd(b,a%b,x1,y1);
x=y1,y=x1-a/b*y1;
return d;
}
long long crt() {
long long M=1,ans=0;
for(int i=1;i<=n;i++) M*=m[i];
for(int i=1;i<=n;i++) {
long long c=M/m[i],x,y;
exgcd(c,m[i],x,y);
ans=(ans+(c*x*a[i])%M)%M;
}
return (ans%M+M)%M;
}
long long mul(long long a,long long b,long long mod) {
long long ans=0;
while(b>0) {
if(b&1) ans=(ans+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return ans;
}
long long excrt() {
long long m1,m2,a1,a2;
m1=m[1],a1=a[1];
for(int i=2;i<=n;i++) {
m2=m[i],a2=a[i];
long long p,q;
long long d=exgcd(m1,m2,p,q);//注意这里 a2-a1 并非是 gcd(m1,m2)
// if((a2-a1)%d) return -1;裴蜀定理判断是否有解,这里不用
long long k=m2/d,c=(((a2-a1)/d)%m2+m2)%m2;
p=mul(p,c,k);//a2-a1 是 gcd(m1,m2) 的倍数,这里求出正确的特解
p=(p%k+k)%k;//保证最小
a1=m1*p+a1,m1=m1*(m2/d);
a1%=m1;
}
return (a1%m1+m1)%m1;
}
long long a,b,p;
map<long long,long long> mp;
long long bsgs() {
long long m=sqrt(p);
if(m*m!=p) m++;
mp[b]=0;
for(long long i=1;i<m;i++) {
b=(b*a)%p;
mp[b]=i;
}
long long k=1;
for(int i=1;i<=m;i++) k=(k*a)%p;
long long i,j,t=1;
for(i=1;i<=m;i++) {
t=(t*k)%p;
if(mp.count(t)) return i*m-mp[t];
}
return -1;
}
为什么要求 a,p 互质
### 扩展 BSGS
[模版](https://www.luogu.com.cn/problem/P4195)。
你猜同余方程的内容为什么会出现在不定方程里。
相较于 BSGS,本题 $a,p$ 不互质。
#### 求解方法
将同余方程 $a^x\equiv b\pmod p$ 化为 $a\times a^{x-1}\equiv b\pmod p$,进一步变为不定方程 $a\times a^{x-1}+py=b$,将 $a,p$ 视为常数,设 $d=\gcd(a,p)$,则若 $d\nmid b$,方程无解,否则将 **同余方程** 两边同除 $d$,得 $\dfrac{a}{d}a^{x-1}\equiv \dfrac{b}{d}\pmod{\dfrac{p}{d}}$,记 $p'=\dfrac{p}{d}$,若 $\gcd(a,p')\not=1$ 则继续直到 $a\perp p'$。记 $D=\dfrac{p}{p'}$,共进行了 $k$ 次,则 $\dfrac{a^k}{D}a^{x-k}\equiv b\pmod {p'}$,由于有 $a\perp p'$,所以有 $\dfrac{a^k}{D}\perp p'$,两边同乘它的逆元后就变为了 BSGS。
```cpp
long long bsgs(int A) {
long long m=sqrt(p);
if(m*m!=p) m++;
mp[b]=0;
for(long long i=1;i<m;i++) {
b=(b*a)%p;
mp[b]=i;
}
long long k=1;
for(int i=1;i<=m;i++) k=(k*a)%p;
long long i,j,t=A;//注意这里 t 从 a^k/D 开始
for(i=1;i<=m;i++) {
t=(t*k)%p;
if(mp.count(t)) return i*m-mp[t];
}
return -1;
}
long long exbsgs() {
if(b==1||p==1) return 0;
long long d,k=0,A=1;
while(true) {
d=gcd(a,p);
if(d==1) break;
if(b%d) return -1;
k++,b/=d,p/=d,A=(A*(a/d))%p;
if(A==b) return k;
}
long long ans=bsgs(A);
if(ans==-1) return -1;
else return ans+k;//记得算出来的是 x-k 要加 k
}
```