P4783 【模板】矩阵求逆
原题链接 https://www.luogu.org/problemnew/show/P4783
一道模板题,更重要的省选难度.....
题目要求的是一个n*n的逆矩阵,还要对大数取膜。
普通高中生:这…………
来一步一步分析:
(1)怎么求逆矩阵?

首先,我们要开一个二维数组,范围是a[401][801];
why?这就和求逆矩阵有关啦。
先输入n*n的矩阵,紧接着在右边罗一个n*n的单位矩阵
然后我们对左半边的矩阵进行高斯消元消成了单位矩阵,则此时右半边的单位矩阵就被消成了左半边原矩阵的逆矩阵
scanf("%lld",&n);
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
scanf("%lld",&a[i][j]);
a[i][i+n]=; //在输入矩阵的同时在右边罗列一个n*n的单位矩阵
}
接着就要对左半边的矩阵进行高斯消元,怎么高斯消元呢?其实就是把高斯消元的板子套上去啊。P3389
这是模板高斯消元的代码:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,pl;
double a[][];
int main()
{
cin>>n;
for(int i=;i<=n;i++)
for(int j=;j<=n+;j++)
cin>>a[i][j];
for(int i=;i<=n;i++)
{
pl=i;
while(a[pl][i]==&&pl<=n)
{pl++;} // 判断第i列首元素非0的最上行,因为第i行第i列元素不能为0
if(pl==n+) {cout<<"No Solution";return ;} //一直判到了n+1行,可是一共才只有n行,说明有一列全为0,无解
for(int j=;j<=n+;j++) //将第i行第i列元素不为0的那一行与当前行交换
swap(a[i][j],a[pl][j]);
double k=a[i][i]; //让第i行每个元素都除以a[i][i]使得a[i][i]为1
for(int j=;j<=n+;j++)
a[i][j]=a[i][j]/k; //将第i行第i列的元素消成1,注意同行进行同样的操作
for(int j=;j<=n;j++)
{
if(i!=j) //将第i列除了第i行的元素全消成0
{ //方法是第j行每个元素a[j][m]都减去a[j][1]*a[i][m]
double ki=a[j][i];
for(int m=;m<=n+;m++)
a[j][m]=a[j][m]-ki*a[i][m];
}
}
}
for(int i=;i<=n;i++)
printf("%.2lf\n",a[i][n+]);
return ;
}
(2)怎么对有理数取膜?
这也是道模板题…………P2613
#include<iostream>
#include<cstdio>
using namespace std;
const long long mod=;
inline long long read()
{
long long t=;
char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='')
{
t=(t*+(ch-''))%mod;
ch=getchar();
}
return t;
}
int exgcd(long long a,long long b,long long &x,long long &y)
{
if(b==)
{
x=;y=;
return a;
}
long long r=exgcd(b,a%b,x,y);
long long q=x;
x=y;
y=q-a/b*y;
return r;
}
int main()
{
long long a,b,x,y;
a=read();
b=read();
if(b==)
{
cout<<"Angry!";
return ;
}
exgcd(b,mod,x,y);
x=(x%mod+mod)%mod;
printf("%lld",(a%mod*x%mod)%mod);
return ;
}
证明过程:
1.费马小定理
如果p是一个质数,而整数a不是p的倍数,则有a^(p-1)≡1(mod p)。
此题已经明确给出mod数19260817,显然它是一个质数,那么我们就可以用费马小定理转化一下,如下:
因为a^(p-1)≡1(mod p)
所以a^(p-2)≡a^(-1) (mod p) (A)
所以c=a/b=a*b^(-1)≡a*b^(p-2) (mod p)
证毕!
所以我们就可以将在膜p意义下的a/b转化成a*b^(p-2)的形式,所以我们只要求出b^(p-2)就大功告成啦,具体做法用快速幂。
2.扩展欧几里德
上面已经证过求在膜p意义下的a/b就是求a*b^(-1),b^(-1)就是b的逆元
下面给出求b的逆元的一种方法:
若存在一个数x,满足bx≡1 (mod p),那么x就是b的逆元
可将bx≡1 (mod p)进一步转化:
bx-1≡0 (mod p)
bx-1=-yp (注:这里说一下为什么是-y,其实这里是不是正负无所谓,写成负的更便于理解)
bx+py=1
二者一结合,就是此题的代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<math.h>
using namespace std;
const int mod=;
long long n,a[][];
long long x,y;
inline int read()
{
int t=;
char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''||ch<='')
{
t=t*+(ch-'');
ch=getchar();
}
}
int inv(long long a,long long b)
{
long long ans=;
while(b)
{
if(b&) ans=ans*a%mod;
a=a*a%mod;
b>>=;
}
return ans%mod;
}
int main()
{
scanf("%lld",&n);
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
scanf("%lld",&a[i][j]);
a[i][i+n]=; //在输入矩阵的同时在右边罗列一个n*n的单位矩阵
}
for(int i=;i<=n;i++) //进行高斯消元
{
for(int j=i;j<=n;j++)
{
if(a[j][i])
{
for(int q=;q<=*n;q++)
swap(a[j][q],a[i][q]);
break;
}
}
if(!a[i][i]) //判无解
{
cout<<"No Solution";return ;
}
long long k=inv(a[i][i],mod-)%mod; //利用费马小定理来求逆元
for(int j=;j<=*n;j++) a[i][j]=a[i][j]*k%mod; //利用矩阵性质将a[i][i]消成1,注意同样对右半边的单位矩阵操作
for(int j=;j<=n;j++) //将第i列的其他行消成0
{
if(j!=i)
{
long long k=a[j][i];
for(int m=i;m<=*n;m++) //注意同时对右半边的单位矩阵进行操作
{
a[j][m]=a[j][m]-k*a[i][m];
a[j][m]=(a[j][m]%mod+mod)%mod;
}
}
}
}
for(int i=;i<=n;i++)
{
for(int j=+n;j<=*n;j++) //输出右半边的矩阵就是逆矩阵啦
cout<<a[i][j]<<" ";
cout<<endl;
}
return ; //完结撒花
}
话说真的这道题就是两个模板题的结合qwq~
P4783 【模板】矩阵求逆的更多相关文章
- luoguP4783 [模板]矩阵求逆 线性代数
求\(n^2\)的矩阵的逆 翻了翻题解,看到了初等矩阵这个东西,突然想起来在看线代的时候看到过.... 然后又温习了一遍线性代数的知识 不妨设\(PA = E\),其中\(P\)是一堆初等矩阵的积(必 ...
- 洛谷 P4783 【模板】矩阵求逆
题目分析 模板题. #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1e ...
- LUOGU P4783 【模板】矩阵求逆(高斯消元)
传送门 解题思路 用高斯消元对矩阵求逆,设\(A*B=C\),\(C\)为单位矩阵,则\(B\)为\(A\)的逆矩阵.做法是把\(B\)先设成单位矩阵,然后对\(A\)做高斯消元的过程,对\(B\)进 ...
- 题解 P4783 【【模板】矩阵求逆】
题目大意 求一个N×N的矩阵的逆矩阵.答案对10^9+7取模.N<=400 前置知识 矩阵的初等变换 矩阵的逆定义为 A*B=E(E为单位矩阵)此时B为A的逆 思路 如果矩阵有逆 那么这个矩阵经 ...
- 洛谷P4783 【模板】矩阵求逆(高斯消元)
题意 题目链接 Sol 首先在原矩阵的右侧放一个单位矩阵 对左侧的矩阵高斯消元 右侧的矩阵即为逆矩阵 // luogu-judger-enable-o2 #include<bits/stdc++ ...
- LG4783 【模板】矩阵求逆
P4783 [模板]矩阵求逆 题目描述 求一个$N\times N$的矩阵的逆矩阵.答案对$10^9+7$取模. 输入输出格式 输入格式: 第一行有一个整数$N$,代表矩阵的大小: 从第$2$行到第$ ...
- matrix矩阵求逆 与解方程模板 留做备用 (有bug,待补充)
// // main.cpp // 矩阵求逆 // // Created by 唐 锐 on 13-6-20. // Copyright (c) 2013年 唐 锐. All rights reser ...
- Luogu4783 【模板】矩阵求逆(高斯消元)
对矩阵进行高斯消元直至消为单位矩阵,并在另一个单位矩阵上对其做同样的操作即可. 模意义下的高斯消元可以直接计算系数来避免整行的辗转相除. 还不知道有什么用. #include<iostream& ...
- OpenCV2邻域和模板操作
在图像处理中,通过当前位置的邻域像素计算新的像素值是很常见的操作.当邻域包含图像的上几行和下几行时,就需要同时扫描图像的若干行,这就是图像的邻域操作了.至于模板操作是实现空间滤波的基础,通常是使用一个 ...
随机推荐
- Skywalking部署常见问题以及注意事项
Skywalking部署常见问题以及注意事项 Intro SkyWalking 创建与2015年,提供分布式追踪功能.从5.x开始,项目进化为一个完成功能的Application Performanc ...
- Cube的高级设置
分享来源地址:http://bigdata.51cto.com/art/201705/538648.htm Cube的高级设置 随着维度数目的增加,Cuboid 的数量会爆炸式地增长.为了缓解 Cub ...
- C# List集合去重使用lambda表达式
name age sex Lucy 22 woman Lily 23 woman Tom 24 man Lucy 22 woman Lily 23 woman LiLei 25 man List< ...
- c/c++ 多线程 mutex的理解
多线程 mutex的理解 mutex,我的理解是每个mutex对象都是一个带锁头的门,这个门有两个状态,门开着和门关着,感觉像是废话... 当想查看门的里东西,或者把东西放进门里,或者从门里拿出东西前 ...
- MFC自绘菜单
自绘控件问题多多.本文以菜单为例. ①当要使用顶层菜单资源.对话框资源.状态栏资源等这3种资源的任何一种.那么CWinApp::InitInstance函数内部必须使用LoadFrame函数来加载资源 ...
- 周一01.4安装PyCharm步骤
安装集成开发工具 步骤一 步骤二 步骤三 步骤四
- Elixir 简介
概述 Elixir 是一种基于 Erlang 虚拟机的函数式,面向并行的通用语言, 它是一门通用语言,所以不仅可以用在擅长的高可用,高并发场景下,也可以用在 web 开发等场景下. Erlang 诞生 ...
- 调用远程主机上的 RMI 服务时抛出 java.rmi.ConnectException: Connection refused to host: 127.0.0.1 异常原因及解决方案
最近使用 jmx 遇到一个问题,client/server 同在一台机器上,jmx client能够成功连接 server,如果把 server 移植到另一台机器上192.168.134.128,抛出 ...
- 周末班:Python基础之模块
什么是模块 什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写 ...
- ES6 快速入门
ES6 初识 ES6 是 ECMAScript 6.0 的简写,即 JavaScript 语言的下一代标准,已经在 2015年6月正式发布了,它的目标是让JS能够方便的开发企业级大型应用程序,因此,E ...