逆元:用于计算式子 (a/b) mod p,当b十分大的时候,可以利用b的逆元inv(b),原式即为(a*inv(b) mod p)。一个类似于b的倒数的家伙,要注意的是b的逆元并不唯一,而且要说成是b模p的情况下逆元是多少。逆元不是一定存在的,必须是b与p互质(两者公因数仅有1)才存在逆元。
求解逆元的方法,目前博主学了两个:
- 利用费马小定理快速幂求逆元。
- 利用拓展欧几里得算法求逆元。
1.利用费马小定理求解逆元:(这个解法仅适用于p为质数)公式为:inv(a)≡a的p−2次幂。
代码实现:
long long ksm(long long a,long long b)
{
if(b<0) return 0;
long long ret=1;
a%=mod;
while(b)
{
if(b&1ll)
ret=(ret*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return ret;
}
long long inv(long long a)
{
return ksm(a,mod-2);
}
2.利用拓展欧几里得算法实现。
代码实现:
typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y){
if(!b)
{
x=1;
y=0;
return a;
}
int r=exgcd(b,a%b,x,y);
int t=y;
y=x-(a/b)*y;
x=t;
return r;
}
在模板中,a为要求逆元的数,b为a要模的数即为mod,x为a mod b的逆元,y为b mod a的逆元。(mod一会是个数词,一会是个动词,嘎嘎),r为a,b的最大公约数,r若不为1,则逆元不存在。