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邻域和模板操作
在图像处理中,通过当前位置的邻域像素计算新的像素值是很常见的操作.当邻域包含图像的上几行和下几行时,就需要同时扫描图像的若干行,这就是图像的邻域操作了.至于模板操作是实现空间滤波的基础,通常是使用一个 ...
随机推荐
- HTML5移动端拖动惯性
下面代码只是实现了上下滑动惯性,没有写水平滑动惯性.(临时代码笔记,可能会在以后的过程中不断更新优化代码) /** * 惯性原理: * 产生的速度 = 移动距离 / 移动时间 * 距离 = 松开的坐标 ...
- 安装完成Dynamics 365 CE后别忘了更改维护作业的运行时间
摘要: 微软动态CRM专家罗勇 ,回复309或者20190308可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . 安装完毕Dy ...
- Hive之SerDe&Beeline
一.SerDe SerDe:Serializer and Deserializer 序列化及反序列化,构建在数据存储和执行引擎之间,对两者实现解耦. Hive通过ROW FORMAT DELIMITE ...
- vue(1)——node.js安装使用,利用npm安装vue
node node简介 node.js也是用js开发的语言,而且是一门服务端语言,更有大神利用node写了一个操作系统出来——NodeOS node能干什么 自带下载工具: 对于我们开发前端项目,no ...
- c:\windows\system32\config\systemprofile\desktop 打不开
Question 重启开机后显示桌面打不开: 再次重启后无效 Solution 打开注册表regedit如下路径,复制Desktop值到 同路径下的Desktop中,再重启.
- 数据库之redis篇(1)—— redis数据库安装,简单使用
简介 reids,由Salvatore Sanfilippo写的一个高性能的key-value数据库,并且它是非关系型数据库,也就是没有像mysql那样多表链接操作,并且它是是完全开源免费的,遵守BS ...
- SQLServer之通过视图修改数据
通过视图增删改数据注意事项 需要对目标表的 UPDATE.INSERT 或 DELETE 权限(取决于执行的操作). 如果视图引用多个基表,则不能删除行. 如果视图引用多个基表,只能更新属于单个基表的 ...
- c/c++ linux epoll系列1 创建epoll
linux epoll系列1 创建epoll 据说select和poll的弱点是,随着连接(socket)的增加,性能会直线下降. epoll不会随着连接(socket)的增加,性能直线下降. 知识点 ...
- 用SQL语句实现:当A列大于B列时选择A列否则选择B列,当B列大于C列时选择B列否则选择C列。
数据库中有A B C三列,用SQL语句实现:当A列大于B列时选择A列否则选择B列,当B列大于C列时选择B列否则选择C列. 方法一: select (case when a>b then a el ...
- 修改 TeamViewer ID 的方法
TeamViewer 使用频繁后会被判定为商业用途,不可用.此软件的账号和设备mac地址绑定. 修改TeamViewer ID后可以重新开始使用.下述方法可以成功修改TeamViewer ID. 关闭 ...