逆元

什么是逆元:

比如a/b%m=c;
d是b的逆元
则a*d%m=c,且bd=1;

逆元有什么用:

当你求解公式(a/b)%c的时候,b的值过大,可能会爆精度,因为除法不能分子和分母同取模一个数除出来的结果还是一样的,所以这个时候你就需要用到逆元,将之变为乘法运算,因为乘法运算可以边乘边取模,所以不会爆精度。

逆元定理:

(a/b)%m=c (1)
假设存在一个数x满足
ax%m=c (2)
由模运算对乘法成立,对第一个式子两边同时乘以 b ,得到:
a%m=(c
(b%m))%m
如果 a 和 b 均小于模数 m 的话,上式可以改写为:
a =bc%m
等式两边再同时乘以 x, 可以得到:
a
x%m=xbc%m
(2)式中c肯定比m小,于是可以化为:
ax%m=c%m
再和上式连起来得到:
c%m=x
bc%m
因此可以得到:
b
x%m=1(!!!b与x是逆元关系)
哎,x是b的逆元呀(x 在模运算的乘法中等同于 1/b(也不完全是), 这就是逆元的意义)
在此,除法取模运算就变成乘法取模运算了。不止是解决了这个问题,还有输入任意的俩个互质数:b,m
b%m恒成立,必须要借助一个x,此x就为b的逆元。
例如:
22%5!=1
22*3%5=1

逆元的求解方法:
法一:费马小定理

当m是一个质数的时候可以利用费马小定理 :
bm-1 %m=1(都说了是定理,不多做解释)
因为很多比赛模的数都是质数,所以说这个解法非常的实用啊!
可以直接得到 b 的逆元是 bm-2,因为b*bm-2%m=1 使用 快速幂 求解即可   
所以bm-1即为b在 mod m 意义下的逆元

long long inv(long long a) //此处a代替b,意义是一样的
{  
    return quickpow(a, m - 2);  //此处为快速幂取模
}  
法二:扩展欧几里德(又叫辗转相除法在这里作逆运算)

首先需要知道gcd(a,b)是由辗转相除法得到最大公约数的方法
即gcd(a,b)=m,此时m就是a和b的最大公约数。
且a不断的在模b求得的m。
如果a、b是整数,那么一定存在整数x、y使得ax+by=gcd(a,b)。
例如 如果ax+by=1有解,那么gcd(a,b)=1;
但是对于上面的式子ax+by=m来说,我们并不仅仅想要知道有没有解,而是想要知道在有解的情况下这个解到底是多少。
当到达递归边界的时候,b=0,a=gcd(a,b),这是毋庸置疑的
这时可以观察出来这个式子的一个解:a1+b0=gcd(a,b),x=1,y=0
注意这时的a和b已经不是最开始的那个a和b了
所以我们如果想要求出解x和y,就要回到最开始的模样。
假设当前我们在求的时a和b的最大公约数,而我们已经求出了下一个状态:b和a%b的最大公因数,并且求出了一组x1和y1使得
b* x1+(a%b) * y1=gcd(b,a%b)
我们知道a%b=a-(a/b)*b
联立得:
bx1 + (a-(a/b)b)y1
= b
x1 + a
y1 – (a/b)by1
= a
y1 + b
(x1 – a/by1) = gcd 发现 x = y1 , y = x1 – a/by1
这样我们就得到了每两个相邻状态的x和y的转化
就可以在求gcd的同时对x和y进行求值了!
此时x为a模b的逆元
则 (x%p+p)%p 即为 b 的逆元((x%p+p)%p为x的最小正整数解)。
注意在递归里面总是先得到后面的解!!!

void exgcd(ll a, ll b, ll &x, ll &y)    //拓展欧几里得算法
{
    if(!b) 
    {
    	x=1;
    	y=0;
    }
    else
    {
        exgcd(b, a % b, y, x);
        y =y - x * (a / b);//此时y和x是互换了的
    }
}
ll niyuan(ll a, ll b)   //求a对b取模的逆元
{
    ll x, y;
    exgcd(a, b, x, y);
    return (x + b) % b;
}
法三:扩展欧几里德(递归写法)

设x = m % a , y = m / a
于是有 x + y * a = m
(x + y * a) % m = 0
移项得 x % m = (-y) * a % m
x * inv(a) % m = (-y) % m
inv(a) = (m – y) * inv(x) % m
于是inv(a) = (m – m / a) * inv(m % a) % m
然后一直递归到1为止,因为1的逆元就是1

ll inv(ll a)   
{  
    return a == 1 ? 1 : (m - m / a) * inv(m % a) % m;  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值