同余
扩展欧几里得算法
扩展欧几里得算法,也叫 。
时间复杂度为 。
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;
}

浙公网安备 33010602011771号