关于 exgcd求逆元 我的理解
Posted Key Key Key
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于 exgcd求逆元 我的理解相关的知识,希望对你有一定的参考价值。
笔者蒟蒻一只,如有错误和不准确不严谨的地方望指正 orz
逆元
我们有时会在求概率等或答案为分数的题目中遇到求逆元的情况
模板->航电 hd-1576
遇到了求\\(\\bf{\\frac{A}{B}}\\)mod P 的问题
题目保证B和P互质
给出 n (A mod P 的值) 、B 、P
我们知道
\\[(A+B) mod P = \\big((A mod P)+(B mod P)\\big)mod P
\\]
\\[(A-B) mod P = \\big((A mod P)-(B mod P)\\big)mod P
\\]
\\[(A\\times B) mod P = \\big((A mod P)\\times (B mod P)\\big)mod P
\\]
但是
\\[(A \\div B) mod P \\neq \\big((AmodP)\\div (BmodP)\\big)mod P
\\]
那该怎么办呢
我们可以想办法将它化成乘法形式 满足上面的第三个公式
学过倒数,我们想到了
\\[(A \\div B)mod P=(\\frac{A}{B})mod P=(A\\times B^{-1})mod P
\\]
那么,由上述的关于乘方取余数的式子得到
\\[(A\\times B^{-1}) mod P = \\big((A mod P)\\times (B^{-1} mod P) \\big)mod P
\\]
由题目得 A mod P 的值为 n
之后题目就转化成了 求 \\(\\frac{1}{B}\\)mod P 的值
问题又来了 \\(\\frac{1}{B}\\) 的值该怎么求呢
它满足
\\[(B\\times B^{-1}) mod P=1
\\]
所以定义 \\(\\frac{1}{B}\\) 叫做B关于P的逆(B也是 \\(\\frac{1}{B}\\) 关于P的逆元
可以表示为
\\[B\\equiv B^{-1}(mod\\;P)
\\]
继续进行式子的变形 上上一个式子等价于
\\[B\\times B^{-1}=1+k\\times P\\qquad k\\ge0
\\]
\\[B\\times B^{-1}-k\\times P=1\\qquad k\\ge0
\\]
到此就用到了扩展欧几里得 exgcd
\\[扩展欧几里得:给予二整数 a 与 b, 必存在有整数 x 与 y 使得ax + by = gcd(a,b)
\\]
这里使用exgcd就求出来 B 的逆元 了
接着返回题目中 用 B的逆元 乘 n 再对 P 取模就可了
扩展欧几里得 exgcd
\\[ax+by=gcd(a,b)
\\]
\\[ax+by=gcd(b,a\\,mod\\,b)
\\]
\\[ax+by=bx_{0}+(a\\,mod\\,b)y_{0}
\\]
\\[ax+by=bx_{0}+(a-(\\lfloor {\\frac {a} {b}}\\rfloor\\times b)y_{0}
\\]
\\[ax+by=bx_{0}+ay_{0}-\\lfloor {\\frac {a} {b}}\\rfloor\\times by_{0}
\\]
\\[ax+by=ay_{0}+b(x_{0}-\\lfloor {\\frac {a} {b}}\\rfloor\\times y_{0})
\\]
通过这一波转化就可以把公式递归下去了
code
exgcd:
ll exgcd(ll a,ll b,ll &x,ll &y){
if(!b){x=1;y=0;return a;}
ll tx=x,ty=y;
ll g=exgcd(b,a%b,tx,ty);
ll t=x;
x=ty;
y=tx-(a/b)*ty;
}
求逆元 (求 n 关于 m 的逆元):
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1,y=0;
return a;
}
ll r = exgcd(b,a%b,x,y);
ll t = x;
x = y;
y = t - a/b*y;
return r;
}
ll inv(ll n,ll m){
ll x,y;
ll ans = exgcd(n,m,x,y);
if(ans == 1)
return (x%m+m)%m;
else
return -1;
}
hd-1576:
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1,y=0;
return a;
}
ll r = exgcd(b,a%b,x,y);
ll t = x;
x = y;
y = t - a/b*y;
return r;
}
ll inv(ll n,ll m){
ll x,y;
ll ans = exgcd(n,m,x,y);
if(ans == 1)
return (x%m+m)%m;
else
return -1;
}
int main(){
ll n,m;
ll t;
cin>>t;
while(t--){
cin>>n>>m;
ll ans = inv(m,9973);
cout<<(n*ans)%9973<<endl;
}
return 0;
}
以上是关于关于 exgcd求逆元 我的理解的主要内容,如果未能解决你的问题,请参考以下文章