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 ...
随机推荐
- 通过全备+binlog_server同步恢复被drop的库或表
MySQL 中drop 等高危误操作后恢复方法 实验目的: 本次实验以恢复drop操作为例,使用不同方法进行误操作的数据恢复. 方法: 利用master同步 :伪master+Binlog+同步(本文 ...
- 13-JS中的面向对象
创建对象的几种常用方式 1.使用Object或对象字面量创建对象 2.工厂模式创建对象 3.构造函数模式创建对象 4.原型模式创建对象 1.使用Object或对象字面量创建对象 JS中最基本创建对象的 ...
- redux最佳实践
对于初学者,redux的理念很难理解.其实redux并不难,redux核心理念就是数据仓库,所有数据操作来源都是明确的.只不过不是直接操作数据,而是交给特定的角色做特定的工作,分工明确. pro ...
- (四)CXF处理JavaBean以及复合类型
前面讲的是处理简单类型,今天这里来讲下CXF处理JavaBean以及复合类型,比如集合: 这里实例是客户端传一个JavaBean,服务器端返回集合类型: 在原来的项目实例基础上,我们先创建一个实体类U ...
- JQuery编写自己的插件(七)
一:jQuery插件的编写基础1.插件的种类编写插件的目的是给一系列已经方法或函数做一个封装,以便在其他地方重复使用,方便后期维护和提高开发效率.常见的种类有以下三种:封装对象方法的插件
- Array,ArrayList,泛型List比较
在C#中数组Array,ArrayList,泛型List都能够存储一组对象,但是在开发中根本不知道用哪个性能最高,下面我们慢慢分析分析. 一.数组Array 数组是一个存储相同类型元素的固定大小的顺序 ...
- 单一职责原则(Simple responsibility pinciple, SRP)
一个类只负责一个功能领域中的相应职责 未完待续
- javax.inject包
javax.inject包 java提出的依赖注入标准,有别于以下传统的对象获取方式 构造方法 工厂模式 服务器定位模式(e.g. JNDI) 开发过程中是会有很多层层依赖的对象的,例如,Stopwa ...
- [转] equals和==的区别小结
==: == 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象.比较的是真正意义上的指针操作. 1.比较的是操作符两端的操作数是否是同一个对象 ...
- python全栈开发day23-面向对象高级:反射(getattr、hasattr、setattr、delattr)、__call__、__len__、__str__、__repr__、__hash__、__eq__、isinstance、issubclass
一.今日内容总结 1.反射 使用字符串数据类型的变量名来操作一个变量的值. #使用反射获取某个命名空间中的值, #需要 #有一个变量指向这个命名空间 #字符串数据类型的名字 #再使用getattr获取 ...