【题解】Matrix BZOJ 4128 矩阵求逆 离散对数 大步小步算法
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4128
大水题一道
使用大步小步算法,把数字的运算换成矩阵的运算就好了
矩阵求逆?这么基础的线代算法我也不想多说,还是自行百度吧
需要注意的是矩阵没有交换律,所以在计算$B\cdot A^{-m}$的时候不要把顺序搞混
代码:
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
#include <cmath> using namespace std;
const int MAXN = ; int n, p; struct Matrix {
int a[MAXN][MAXN];
int *operator[]( int idx ) {
return a[idx];
}
const int *operator[]( int idx ) const {
return a[idx];
}
bool operator<( const Matrix &rhs ) const { // 用于map
for( int i = ; i < n; ++i )
for( int j = ; j < n; ++j )
if( a[i][j] < rhs[i][j] ) return true;
else if( a[i][j] > rhs[i][j] ) return false;
return false;
}
void unit() { // 填成n阶单位矩阵
memset( a, , sizeof(a) );
for( int i = ; i < n; ++i ) a[i][i] = ;
}
void clear() { // 填成全0
memset( a, , sizeof(a) );
}
};
Matrix A, B; // 题目中给定的A,B矩阵 int pow_mod( int a, int b ) { // 整数快速幂
int ans = ;
while(b) {
if( b& ) ans = ans * a % p;
a = a * a % p;
b >>= ;
}
return ans;
}
int inv( int a ) { // 整数求逆
return pow_mod(a,p-);
}
void input_matrix( Matrix &A ) {
for( int i = ; i < n; ++i )
for( int j = ; j < n; ++j ) {
scanf( "%d", &A[i][j] );
A[i][j] %= p;
}
}
void mul( const Matrix &A, const Matrix &B, Matrix &C ) { // 矩阵乘法,结果存入C
Matrix tmp; tmp.clear();
for( int i = ; i < n; ++i )
for( int j = ; j < n; ++j )
for( int k = ; k < n; ++k )
tmp[i][j] = (tmp[i][j] + A[i][k] * B[k][j] % p) % p;
C = tmp;
}
void gauss_jordan( int A[MAXN][MAXN<<] ) { // 高斯约当消元求逆
for( int i = ; i < n; ++i ) {
int r;
for( r = i; r < n; ++r )
if( A[r][i] ) break;
if( r != i )
for( int j = i; j < (n<<); ++j )
swap( A[r][j], A[i][j] );
int iv = inv( A[i][i] );
for( int j = i; j < (n<<); ++j )
A[i][j] = A[i][j] * iv % p;
for( int j = ; j < n; ++j )
if( j != i && A[j][i] ) {
int tmp = (p - A[j][i]) % p;
for( int k = i; k < (n<<); ++k )
A[j][k] = (A[j][k] + A[i][k] * tmp % p) % p;
}
}
}
void inv( const Matrix &A, Matrix &B ) { // 矩阵求逆,结果存入B
int tmp[MAXN][MAXN<<] = {};
for( int i = ; i < n; ++i )
for( int j = ; j < n; ++j )
tmp[i][j] = A[i][j];
for( int i = ; i < n; ++i ) tmp[i][i+n] = ;
gauss_jordan(tmp);
for( int i = ; i < n; ++i )
for( int j = ; j < n; ++j )
B[i][j] = tmp[i][j+n];
} map<Matrix,int> mp;
int bsgs( Matrix A, Matrix B ) { // 大步小步算法
int m = sqrt(p)+;
Matrix E; E.unit();
for( int i = ; i < m; ++i ) {
if( !mp.count(E) ) mp[E] = i;
mul(E,A,E);
}
inv(E,E);
for( int i = ; i < p; i += m ) {
if( mp.count(B) ) return i + mp[B];
mul(B,E,B); // 注意矩阵乘法顺序
}
return -;
} int main() {
scanf( "%d%d", &n, &p );
input_matrix(A), input_matrix(B);
printf( "%d\n", bsgs(A,B) );
return ;
}
【题解】Matrix BZOJ 4128 矩阵求逆 离散对数 大步小步算法的更多相关文章
- 离散对数&&大步小步算法及扩展
bsgs algorithm ax≡b(mod n) 大步小步算法,这个算法有一定的局限性,只有当gcd(a,m)=1时才可以用 原理 此处讨论n为素数的时候. ax≡b(mod n)(n为素数) 由 ...
- UVA 11916 Emoogle Grid 离散对数 大步小步算法
LRJ白书上的题 #include <stdio.h> #include <iostream> #include <vector> #include <mat ...
- 离散对数及其拓展 大步小步算法 BSGS
离散对数及其拓展 离散对数是在群Zp∗Z_{p}^{*}Zp∗而言的,其中ppp是素数.即在在群Zp∗Z_{p}^{*}Zp∗内,aaa是生成元,求关于xxx的方程ax=ba^x=bax=b的解, ...
- [模板]大步小步算法——BSGS算法
大步小步算法用于解决:已知A, B, C,求X使得 A^x = B (mod C) 成立. 我们令x = im - j | m = ceil(sqrt(C)), i = [1, m], j = [0, ...
- 大步小步算法模板题, poj2417
大步小步模板 (hash稍微有一点麻烦, poj不支持C++11略坑) #include <iostream> #include <vector> #include <c ...
- bzoj 4128 矩阵求逆
/************************************************************** Problem: 4128 User: idy002 Language: ...
- BSGS-Junior·大步小步算法
本文原载于:http://www.orchidany.cf/2019/02/06/BSGS-junior/#more \(\rm{0x01}\) \(\mathcal{Preface}\) \(\rm ...
- [BSGS]大步小步算法
问题 BSGS被用于求解离散对数,即同余方程: \[ A^x\equiv B\pmod{P} \] 求\(x\)的最小非负整数解. 保证\(A\perp P\)(互质). 分析 首先,我们根据费马小定 ...
- BSGS算法(大步小步算法)
计算\(y^x ≡ z \ mod\ p\) 中 \(x\) 的解. 这个模板是最小化了\(x\) , 无解输出\(No \ Solution!\) map<ll,ll>data; ll ...
随机推荐
- (转)GEM -次表面散射的实时近似
次表面散射(Subsurface Scattering),简称SSS,或3S,是光射入非金属材质后在内部发生散射, 最后射出物体并进入视野中产生的现象, 即光从表面进入物体经过内部散射,然后又通过物体 ...
- JAVA基础:ArrayList和LinkedList区别
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList ...
- Ubuntu14.04下部署FastDFS 5.08+Nginx 1.9.14
最新的版本可以在这里获取,目前下载的最新版本是5.08,更新于2016-02-03.在这里可以找到更多的说明. 下载好后,server端分为两个部分,一个是tracker,一个是storage.顾 ...
- “Hello World!”团队第二次会议
今天是我们团队“hello world!”团队召开的第二次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 一.会议时间 20 ...
- psp1111
1 本周psp 2.本周进度条 3.本周累积进度图 代码累积折线图 博文字数累积折线图 4.本周PSP饼状图
- Ubuntu下erlang连接SQL SERVER 2008
erlang连接SQL Server使用ODBC方法,但在网络上还是缺少资料,自己折腾了2天才成功.现在特记录下来,以供大家借鉴. 基本思路是 erlang odbcserver + unixodbc ...
- OSG数学基础:坐标系统
坐标系是一个精确定位对象位置的框架,所有的图形变换都是基于一定的坐标系进行的. 三维坐标系总体上可以分为两大类:左手坐标系和右手坐标系. 常用的坐标系:世界坐标系.物体坐标系和摄像机坐标系. 世界坐标 ...
- VUE01指令
一.下载Vue2.0的两个版本: 官方网站:http://vuejs.org/ 开发版本:包含完整的警告和调试模式 生产版本:删除了警告,进行了压缩 二.项目结构搭建 这个部分要视频中有详细讲解. 三 ...
- 【Docker 教程】- Docker 架构
1.Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器. 2.Docker 容器通过 Docker 镜像来创建. 3.容器与镜像的关系类似于面向对象编程 ...
- navicat for mysql 10.1.7 注册码
NAVN-LNXG-XHHX-5NOO名:组织:注册码:均为NAVN-LNXG-XHHX-5NOO 下载地址:http://www.cr173.com/soft/38153.html