专栏文章
乘法逆元
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miphz5cp
- 此快照首次捕获于
- 2025/12/03 12:18 3 个月前
- 此快照最后确认于
- 2025/12/03 12:18 3 个月前
在实数范围内,当时,一定有
在mod P意义下,我们同样想要这么一个的东西使
“ ”
,那么这个x就称作a在模P意义下的逆元。
为什么我们需要逆元呢?
首先,在计算当中,我们可能需要计算形如“ ”这种算式。由于除法特殊的性质,“并不一定等于”。这个时候我们就需要用逆元把除法转换成乘法。
或者,当我们计算模意义下的除法的时候,我们通常需要边做边模,这样比较省空间,可以有效防止爆范围,这个时候我们也需要使用逆元来把除法转换成乘法。
总之逆元非常的好用,但是怎么去求呢?
首先我们要知道一个定理:裴蜀定理:
对于整数a,b,设他们的最大公约数,则一定存在一组整数解使得
。
那么我们从这个定理又能推出一个定理:对于整数有整数解当且仅当 。
充分性:如果c是的倍数,那么可以先通过裴蜀定理的一组解。然后将同乘以,就得到了不定方程的一组解。必要性:如果不定方程有解,因为是的倍数,同样也是,并且都是整数,所以,也就是c,也一定是的倍数。——《深进》
通过这个定理我们就只需要求出 的一组解就好了。怎么求呢?这个时候我们就要使用伟大的扩欧了。
回忆一下求最大公约数用的欧几里得算法(辗转相除法),然后用它的经验求解这个不定方程:
1.当时,的解就是任意。
2.求出的一组解,记作。
现在我们有了方程的一组解,接下来的问题就是怎么从这组解生成一组新的。
已知,那么可以把用来表示,得到
提公因式,得
又因为
所以有
这个时候可以发现,只要令,这个问题就可以解决了,这样裴蜀定理也就得到了证明。
代码实现:
CPP#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;
ll a,p;
void exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1,y=0;
return;
}
exgcd(b,a%b,y,x);
y-=a/b*x;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n;
cin>>a>>p;
ll x,y;
exgcd(a,p,x,y);
x=(x%p+p)%p;
cout<<x<<endl;
return 0;
}
这样我们得出的x就是a在模P意义上的逆元。
或者,如果我们不想用扩欧,也有另一种方法来做。
费马小定理,指的是如果p是一个质数而整数a不是p的倍数,则有
那通过这个定理我们就能知道,
所以就是a在模P意义下的逆元,那么我们就只需要求就好了
代码实现:
CPP#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;
const int mod=19260817;
string s,t;
ll a,b;
ll fpow(ll x,ll y){
ll t=1;
while(y){
if(y&1) t=t*x%mod;
x=x*x%mod;
y>>=1;
}
return t;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>s>>t;
for(int i=0;i<s.size();i++) a=(a*10+s[i]-'0')%mod;
for(int i=0;i<t.size();i++) b=(b*10+t[i]-'0')%mod;
if(a%mod&&!(b%mod)) cout<<"Angry!";
cout<<a*fpow(b,mod-2)%mod;
return 0;
}
这样我们就算出了a在模P意义上的逆元。但是现在问题又来了:怎么证明在0到p的范围内模P的逆元是唯一的?
我们假设
,
那么就有。
也就是说是的倍数,但是可以发现所以 不是的倍数,于是这个东西就矛盾了。
那么我们就可以证明:在0到的范围内模P的逆元确实是唯一的。
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...