乘法逆元&矩阵求逆
乘法逆元简介
模意义下乘法运算的逆元
- 定义:如果一个线性同余方程
,则 称为 的逆元,记作 。
- 分数取模:设
为 的逆元,则有
费马小定理法
扩展欧几里得法
定理1
线性同余方程
其中
有整数解的充要条件为
对于线性不定方程
定理2
若
并且对任意整数 t 都成立。
根据定理 2,可以从已求出的一个解,求出方程的所有解。实际问题中,往往要求出一个最小整数解,也就是一个特解
其中有
void exgcd(cs int a,cs int b,int &x,int &y)
{
if (!b) return x=1,y=0,void();
exgcd(b,a%b,y,x), y-=a/b*x;
}
int main()
{
int x,y; exgcd(a,Mod,x,y);
x=(x%Mod+Mod)%Mod,wt(x); //x是 a 在 mod p意义下的下的逆元
}
线性求逆元
il void calc()
{
inv[1]=1;
for(ri int i=2;i<=n;++i)
inv[i]=(p-p/i)*inv[p%i]%p;
}
线性求任意 个数的逆元
首先计算
因为
同理我们可以依次计算出所有的
复杂度
点击查看代码
#include<bits/stdc++.h>
#define cs const
#define il inline
#define ri register
#define pc(i) putchar(i)
#define int long long
using namespace std;
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) x=-x,pc('-');if(x>9) wt(x/10);pc(x%10|48);}
cs int N=5e6+7;
int n,Mod,k,a[N],s[N],sv[N],ans,kk;
il int qpow(int base,int power)
{
int re=1;
while(power>0)
{
if(power&1) (re*=base)%=Mod;
power>>=1,(base*=base)%=Mod;
}
return re;
}
signed main()
{
s[0]=1,read(n),read(Mod),read(k),kk=k;
for(ri int i=1;i<=n;++i)
read(a[i]),s[i]=s[i-1]*a[i]%Mod;
sv[n]=qpow(s[n],Mod-2);
for(ri int i=n;i>=1;--i)
sv[i-1]=sv[i]*a[i]%Mod;
for(ri int i=1;i<=n;++i)
(ans+=kk*s[i-1]%Mod*sv[i]%Mod)%=Mod,(kk*=k)%=Mod;
wt(ans);
return 0;
}
矩阵求逆
高斯消元,分数取模用上述方法转化即可
点击查看代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#define il inline
#define ri register
#define pc(i) putchar(i)
#define int long long
using namespace std;
const int Mod=1e9+7,N=500;
int n,a[N][N<<1];
il void wt(int x){if(x<0)pc('-'),x=-x;if(x>9)wt(x/10);pc(x%10+48);}
il int qpow(int b,int p){int re=1;while(p>0){if(p&1)re=re*b%Mod;p>>=1,b=b*b%Mod;}return re%Mod;}
il void Pt(){for(ri int i=1;i<=n;++i){for(ri int j=n+1;j<=n+n;++j)printf("%lld ",a[i][j]);pc('\n');}}
il int inv(int x){return qpow(x,Mod-2)%Mod;}
il int M(int x) {return (x%Mod+Mod)%Mod;}
il void Gauss()
{
for(ri int i=1;i<=n;++i)
{
int Max=i,ai;
for(ri int j=i+1;j<=n;++j) if(abs(a[Max][i])<abs(a[j][i])) Max=j;//upd: >
if(!a[Max][i]) return puts("No Solution"),void();
swap(a[Max],a[i]),ai=inv(a[i][i]);
for(ri int j=1;j<=n;++j)
{
if(j==i) continue;
int p=a[j][i]*ai%Mod;// a[j][i]/a[i][i]%Mod
for(ri int k=1;k<=n+n;++k) a[j][k]=M(a[j][k]-p*a[i][k]);
}
for(ri int k=1;k<=n+n;++k) a[i][k]=a[i][k]*ai%Mod; // a[i][k]/a[i][i]%Mod
}
Pt();
}
signed main()
{
scanf("%lld",&n);
for(ri int i=1;i<=n;++i)
for(ri int j=1;j<=n;++j)scanf("%lld",&a[i][j]),a[i][i+n]=1;
Gauss();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效