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 ...
随机推荐
- C# 清理消息管道的消息
using System;using System.Collections.Generic;using System.Linq;using System.Messaging;using System. ...
- zabbix添加对自定义无规则的关键日志文件的监控
zabbix添加对自定义无规则日志文件的监控 项目背景及思路: zabbix自带有针对日志文件的监控,自带的监控只能监控到指定文件或者正则匹配的固定日志文件,但当需要监控的文件名没有规律的时候自带监控 ...
- C++ code:More Loop Designs
1 逻辑判断 对于逻辑判断问题,一般都要考虑全部的可能性,然后从这些可能性中按条件逐一排查,直到最后获得某个结论. [百钱买百鸡问题] 问题描述: 雄鸡(cock)7元一只,母鸡(hen)5元一只, ...
- poj2464扫描线好题,树状数组解法
用树状数组解比线段树快了好多,难度也下降许多 分别用两个树状数组维护当前扫描线左侧和右侧的点,离散化y轴即可 #include<iostream> #include<cstring& ...
- 基于TCPCopy的仿真压测方案
一.tcpcopy工具介绍 tcpcopy 是一个分布式在线压力测试工具,可以将线上流量拷贝到测试机器,实时的模拟线上环境,达到在程序不上线的情况下实时承担线上流量的效果,尽早发现 bug,增加上线信 ...
- 《剑指offer》-双栈实现队列
题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 很基本的STL容器操作了,应该可以1A的,但是忘记返回值的时候,clang的报错感觉并不友好啊.. cl ...
- Linux学习 用户管理
0.新建用户 sudo useradd -d /home/zookeeper -m zookeeper -d 指定用户组目录 -m 如果前面指定的用户组目录不存在,就创建改目录 passwd 1./e ...
- [转] HTML5应用之文件上传
HTML5解决了以往网页编写的一个难题:带有上传进度的文件上传. 本文的代码全部来自http://www.matlus.com/html5-file-upload-with-progress/,如在技 ...
- 线程池 多线程运行结束后 如何关闭? ExecutorService的正确关闭方法
前言 最近在使用ExecutorService的时候,对于与ExecutorService相关的概念有些迷糊, 加上本身ExecutorService内部的有些方法名在取名上也容易让使用者误解,导致 ...
- Nginx 启动脚本,超级详细
转载自:https://www.cnblogs.com/leffss/p/7845303.html