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邻域和模板操作
在图像处理中,通过当前位置的邻域像素计算新的像素值是很常见的操作.当邻域包含图像的上几行和下几行时,就需要同时扫描图像的若干行,这就是图像的邻域操作了.至于模板操作是实现空间滤波的基础,通常是使用一个 ...
随机推荐
- [ArcGIS API for JavaScript 4.8] Sample Code-Get Started-widgets简介
[官方文档:https://developers.arcgis.com/javascript/latest/sample-code/intro-widgets/index.html] 一.Intro ...
- Arcgis瓦片--js客户端加载
接上篇博客,下载好arcgis格式的瓦片数据以后,需要用js客户端在前端加载出来.这里介绍两种方案: 1.使用超图iServer将瓦片发布成rest地图服务,或者arcgis地图服务,客户端直接加载 ...
- JDBC操作MySQL数据
对原始jdbc进行封装 package com.utils; import java.sql.Connection; import java.sql.DriverManager; import jav ...
- Easyui datagrid combobox输入框非法输入判断与事件总结
datagrid combobox输入框非法输入判断与事件总结 by:授客 QQ:1033553122 测试环境 jquery-easyui-1.5.3 常见事件 onSelect // 选择下拉列表 ...
- Windows系统下搭建Git本地代码库
近由于工作需要,要把工作代码做一下版本管理.工作代码也不方便放到github上,也不想付费建私密库,公司也没几个人,所以就想着搭建一个本地Git版本库,来做版本管理.搭建过程如下. 系统环境:Dell ...
- mean项目的分模块开发
全文字版: 新建maven工程在,作为父工程用于最后集合使用,该工程不需要src,只需要一个pom.xml文件,规定一下依赖版本之类的,再建一个工具类的工程,不需要放配置文件,和工程中方法接口有关的不 ...
- input输入限制,只允许输入数字和“.”,长度不得超过20
<input style="margin-top: 10px;width: 100%;text-align:center;" id="removeArea" ...
- Oracle的ORA-02292报错:违反完整性约束,已找到子记录
第一种方法: 第一步就是找到子表的记录: select a.constraint_name, a.table_name, b.constraint_name from user_constraints ...
- bug优先级别
https://www.cnblogs.com/evablogs/p/6785083.html bug缺陷的优先级别 首先需要对一个版本进行冒烟测试,确定基本功能测试,如果不通过的话进行后期的测试已经 ...
- MySql 学习之路-聚合函数
下面是mysql 数据库中经常用到的聚合函数的简单实例 -- 创建学生表 create table student ( id int primary key auto_increment commen ...