同余
luckydrawbox · · 算法·理论
扩展欧几里得算法
扩展欧几里得算法,也叫
时间复杂度为
long long exgcd(long long a,long long b,long long &x,long long &y){
if(!b){
x=1;y=0;
return a;
}
long long d=exgcd(b,a%b,x,y);
long long z=x;x=y;y=z-y*(a/b);
return d;
}
使用时,提前定义变量 d=exgcd(a,b,x0,y0),程序执行完后
对于更为一般的方程
乘法逆元
不是所有数都有逆元。
若
利用费马小定理求乘法逆元
若保证
需要用到快速幂。
long long qni_fm(long long a,long long p){
return qmi(a,p-2,p);
}
利用扩展欧几里得算法求乘法逆元
若保证
需要用到扩展欧几里得算法。
long long qni_ol(long long a,long long p){
long long x,y;
exgcd(a,p,x,y);
return x;
}
线性同余方程
求
方程的通解是所有模
中国剩余定理
中国剩余定理,也叫
设
有解,解为
long long CRT(int n,long long *a,long long *m){
long long sum=0,M=1,x,y;
for(int i=1;i<=n;i++)
M*=m[i];
for(int i=1;i<=n;i++){
exgcd(M/m[i],m[i],x,y);
sum+=a[i]*M/m[i]*x%M;
}
return (sum%M+M)%M;
}
时间复杂度为
扩展中国剩余定理
扩展中国剩余定理,也叫
若在中国剩余定理的基础上无法满足
long long EXCRT(long long n,long long *a,long long *m){
long long x,y,k,lcm=a[1],ans=m[1],d;
bool f=1;
for(int i=2;i<=n;i++){
m[i]=(m[i]-ans%a[i]+a[i])%a[i];
d=exgcd(lcm,a[i],x,y);
if(m[i]%d)
f=0;
else
k=x*(m[i]/d)%a[i];
ans+=k*lcm;
lcm=lcm/d*a[i];
ans=(ans%lcm+lcm)%lcm;
}
if(f)
return ans;
return -1;
}
若无解会返回
高次同余方程
BSGS算法
对于方程
需要快速幂。
无解返回
时间复杂度为
long long Baby_Step_Giant_Step(long long a,long long b,long long p){
map<long long,long long>hash;
hash.clear();
b%=p;
long long t=(long long)sqrt(p)+1,val;
for(long long j=0;j<t;j++){
val=(long long)b*qmi(a,j,p)%p; // b*a^j
hash[val]=j;
}
a=qmi(a,t,p); // a^t
if(!a)
return b?-1:1;
for(long long i=0;i<=t;i++){
val=qmi(a,i,p); // (a^t)^i
long long j=hash.find(val)==hash.end()?-1:hash[val];
if(j>=0&&i*t-j>=0)
return i*t-j;
}
return -1;
}
back