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 ...
随机推荐
- jenkins cobertura单元测试
1.1 Maven 工程 pom.xml 修改 1.2 Build添加插件目标 此时构建项目,会在项目 targer/site/cobertura 目录中生成 html 与 xml ...
- 转载:磁盘目录(1.3.3)《深入理解Nginx》(陶辉)
原文:https://book.2cto.com/201304/19614.html 要使用Nginx,还需要在Linux文件系统上准备以下目录. (1)Nginx源代码存放目录 该目录用于放置从官网 ...
- [学习笔记]Javascript的包装对象
例子1: var s="test"; s.len = 4; var t = s.len // t is undefined 原因是s是字符串,第二行代码,实际上是创建一个临时字符串 ...
- Golang依赖管理工具:glide从入门到精通使用
这是一个创建于 2017-07-22 05:33:09 的文章,其中的信息可能已经有所发展或是发生改变. 介绍 不论是开发Java还是你正在学习的Golang,都会遇到依赖管理问题.Java有牛逼轰轰 ...
- HTML5事件—visibilitychange 页面可见性改变事件
转:https://blog.csdn.net/yusirxiaer/article/details/73480916 又看到一个很有意思的HTML5事件 visibilitychange事件是浏览器 ...
- CSS----布局注意事项
1.当div标签中含有子标签,如果div标签的大小是被div中的子标签撑起来的,那么可能布局(之后)可能就会出现问题(if 父级div中没有border,padding,inlinecontent,子 ...
- python调用修改变量新方法
def foo(): count = [1] #将变量放在列表中,此时,内部函数就可以修改了 def bar(): count[0] = count[0] + 1 return count[0] re ...
- Java容器---字符容器StringBuffer & StringBuilder
1.字符串对象 (1)定义 ---String 字符串常量,是不可改变的量,也就是创建后就不能在修改了: --- StringBuffer 字符串变量(线程安全),StringBuffer对象的值都是 ...
- python 全栈开发,Day5(字典,增删改查,其他操作方法)
一.字典 字典是python中唯一的映射类型,采用键值对(key-value)的形式存储数据.存储大量的数据,是关系型数据,查询数据快. 列表是从头遍历到尾字典使用二分查找 二分查找也称折半查找(Bi ...
- jquery的clone方法应用于textarea和select的bug修复不能copy值,clone id重复的解决
textarea和select的值clone的时候会丢掉,在clone的时候将val再重新赋值一下,如果知道这个了就简单了, 测试发现,textarea和select的jquery的clone方法有问 ...