bzoj 4128 矩阵求逆
/**************************************************************
Problem: 4128
User: idy002
Language: C++
Result: Accepted
Time:4932 ms
Memory:4152 kb
****************************************************************/ #include <iostream>
#include <cstdio>
#include <cmath>
#include <map>
using namespace std; const int N = ; int n, Mod;
int inv[]; struct Matrix {
int v[N][N];
void unit() {
for( int i=; i<n; i++ )
for( int j=; j<n; j++ )
v[i][j] = (i==j);
}
void read() {
for( int i=; i<n; i++ )
for( int j=; j<n; j++ )
scanf( "%d", &v[i][j] );
}
}; int mpow( int a, int b ) {
int rt;
for( rt=; b; b>>=,a=(a*a)%Mod )
if( b& ) rt=(rt*a)%Mod;
return rt;
} Matrix operator*( const Matrix &a, const Matrix &b ) {
Matrix c;
for( int i=; i<n; i++ ) {
for( int j=; j<n; j++ ) {
c.v[i][j] = ;
for( int k=; k<n; k++ ) {
c.v[i][j] += a.v[i][k] * b.v[k][j] % Mod;
if( c.v[i][j]>=Mod ) c.v[i][j]-=Mod;
}
}
}
return c;
}
Matrix operator~( Matrix a ) {
Matrix b;
b.unit();
for( int i=,j; i<n; i++ ) {
for( int k=i; k<n; k++ )
if( a.v[k][i] ) {
j=k;
break;
}
if( i!=j ) {
for( int k=; k<n; k++ ) {
swap(a.v[i][k],a.v[j][k]);
swap(b.v[i][k],b.v[j][k]);
}
}
for( int j=i+; j<n; j++ ) {
int d = a.v[j][i]*inv[a.v[i][i]] % Mod;
for( int k=; k<n; k++ ) {
a.v[j][k] = (a.v[j][k] - a.v[i][k]*d) % Mod;
b.v[j][k] = (b.v[j][k] - b.v[i][k]*d) % Mod;
if( a.v[j][k]< ) a.v[j][k]+=Mod;
if( b.v[j][k]< ) b.v[j][k]+=Mod;
}
}
}
for( int i=n-; i>=; i-- ) {
int d = inv[a.v[i][i]];
for( int k=; k<n; k++ ) {
a.v[i][k] = a.v[i][k] * d % Mod;
b.v[i][k] = b.v[i][k] * d % Mod;
}
for( int j=i-; j>=; j-- ) {
d = a.v[j][i] * inv[a.v[i][i]] % Mod;
for( int k=; k<n; k++ ) {
a.v[j][k] = (a.v[j][k] - a.v[i][k]*d) % Mod;
b.v[j][k] = (b.v[j][k] - b.v[i][k]*d) % Mod;
if( a.v[j][k]< ) a.v[j][k] += Mod;
if( b.v[j][k]< ) b.v[j][k] += Mod;
}
}
}
return b;
}
bool operator<( const Matrix &a, const Matrix &b ) {
for( int i=; i<n; i++ )
for( int j=; j<n; j++ ) {
if( a.v[i][j] ^ b.v[i][j] )
return a.v[i][j] < b.v[i][j];
}
return false;
}
bool operator==( const Matrix &a, const Matrix &b ) {
for( int i=; i<n; i++ )
for( int j=; j<n; j++ )
if( a.v[i][j] ^ b.v[i][j] ) return false;
return true;
}
int ind( Matrix a, Matrix b ) {
map<Matrix,int> mp;
int m = int(sqrt(Mod))+;
Matrix base = a;
a.unit();
for( int i=; i<m; i++ ) {
if( a==b && i ) return i;
mp[a] = i;
a = a*base;
}
base = ~a;
a = b*base;
for( int i=m; ; i+=m,a=a*base )
if( mp.count(a) ) return i+mp[a];
} int main() {
scanf( "%d%d", &n, &Mod );
for( int i=; i<Mod; i++ )
inv[i] = mpow(i,Mod-);
Matrix a, b;
a.read();
b.read();
printf( "%d\n", ind(a,b) );
}
收获:
1. 矩阵进行如下操作可以相当于用一个矩阵乘以它:
将一行上的所有数乘以k
将一行加到另一行上
交换两行
2. 求逆的过程
如果要求矩阵A的逆矩阵A-1,先得到一个单位矩阵B,
然后用上面1中的三种操作将A变成单位矩阵(不能变成单位矩阵则说明该矩阵行列式为0,即该矩阵不存在逆)
将对A的所有操作同样地应用于B,最终B就是A-1
3. 求逆的正确性
我们对A进行了一系列变换,等同于用一个矩阵C乘以A使得 C*A = I
即C是A的逆矩阵, 将同样的操作作用于B,得到的矩阵为 C*B = C*I = C
即最终B的结果就是我们要求的逆
4. 高斯消元的另一种理解
A*X = B
C*A*X = C*B
完了
bzoj 4128 矩阵求逆的更多相关文章
- 【题解】Matrix BZOJ 4128 矩阵求逆 离散对数 大步小步算法
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4128 大水题一道 使用大步小步算法,把数字的运算换成矩阵的运算就好了 矩阵求逆?这么基础的线 ...
- BZOJ 4128: Matrix
BZOJ 4128: Matrix 标签(空格分隔): OI BZOJ 大步小步 矩阵 费马小定理 Time Limit: 10 Sec Memory Limit: 128 MB Descriptio ...
- BZOJ 4128 Matrix BSGS+矩阵求逆
题意:链接 方法: BSGS+矩阵求逆 解析: 这题就是把Ax=B(mod C)的A和B换成了矩阵. 然而别的地方并没有修改. 所以就涉及到矩阵的逆元这个问题. 矩阵的逆元怎么求呢? 先在原矩阵后接一 ...
- bzoj 4128: Matrix ——BSGS&&矩阵快速幂&&哈希
题目 给定矩阵A, B和模数p,求最小的正整数x满足 A^x = B(mod p). 分析 与整数的离散对数类似,只不过普通乘法换乘了矩阵乘法. 由于矩阵的求逆麻烦,使用 $A^{km-t} = B( ...
- BZOJ 4128 Matrix ——BSGS
矩阵的BSGS. 只需要哈希一下存起来就可以了. 也并不需要求逆. #include <map> #include <cmath> #include <cstdio> ...
- BZOJ 4128: Matrix (矩阵BSGS)
类比整数的做法就行了 1A爽哉 #include<bits/stdc++.h> using namespace std; typedef long long LL; const int M ...
- 【BZOJ】4128: Matrix
题解 学习一下矩阵求逆 就是我们考虑这个矩阵 \(AA^{-1} = I\) 我们相当于让\(A\)乘上一个矩阵,变成\(I\) 我们可以利用初等行变换(只能应用初等行变换,或只应用初等列变换) 分三 ...
- BZOJ 1444 [JSOI2009]有趣的游戏 (Trie图/AC自动机+矩阵求逆)
题目大意:给你$N$个长度相等且互不相同的模式串,现在有一个字符串生成器会不断生成字符,其中每个字符出现的概率是$p_{i}/q_{i}$,当生成器生成的字符串包含了某个模式串,则拥有该模式串的玩家胜 ...
- BZOJ 3168 Luogu P4100 [HEOI2013]钙铁锌硒维生素 (矩阵求逆、二分图匹配)
线性代数+图论好题. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3168 (luogu) https://www.lu ...
随机推荐
- 服务发现之consul的介绍、部署和使用
什么是服务发现 微服务的框架体系中,服务发现是不能不提的一个模块.我相信了解或者熟悉微服务的童鞋应该都知道它的重要性.这里我只是简单的提一下,毕竟这不是我们的重点.我们看下面的一幅图片: 图中 ...
- python+selenium七:下拉框、选项框、select用法
# from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChainsimpo ...
- collectd+influxDB+Grafana搭建性能监控平台
网上查看了很多关于环境搭建的文章,都比较久远了很多安装包源都不可用了,今天收集了很多资料组合尝试使用新版本来搭建,故在此记录. 采集数据(collectd)-> 存储数据(influxdb) - ...
- HDU1536 S-Nim(sg函数变换规则)
S-Nim Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...
- js在字符串中提取数字
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 2018-2019-2 网络对抗技术 20165333 Exp3 免杀原理与实践
实验内容 任务一:正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil-evasion,自己利用shellcode编程等免杀工具或技巧 使用msf编码器生成各种后门程序及检测 使 ...
- 《剑指offer》-整数中1出现的次数
题目描述 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了. ...
- [JSOI2009]等差数列
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1558 题解: 考虑这么用线段树进行维护,由于他有区间修改等差数列 很容易想到可以用差分数组来维 ...
- 6-16 单词 uva10129
了解了欧拉回路和欧拉道路的性质 : 欧拉道路 最多只有两个奇点(不可能只有一个奇点) 并且当有两个奇点的时候 一个奇点入比出多一 一个奇点出比入多一 采用并查集查看是否连同 如果连 ...
- Spring日记_01 之 Eclipse下的Tomcat服务器配置 以及 Springmvc和Servlet的使用
安装Tomcat – window – preferences – Server 右键Tomcat v ...