传送门: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 矩阵求逆 离散对数 大步小步算法的更多相关文章

  1. 离散对数&&大步小步算法及扩展

    bsgs algorithm ax≡b(mod n) 大步小步算法,这个算法有一定的局限性,只有当gcd(a,m)=1时才可以用 原理 此处讨论n为素数的时候. ax≡b(mod n)(n为素数) 由 ...

  2. UVA 11916 Emoogle Grid 离散对数 大步小步算法

    LRJ白书上的题 #include <stdio.h> #include <iostream> #include <vector> #include <mat ...

  3. 离散对数及其拓展 大步小步算法 BSGS

    离散对数及其拓展 离散对数是在群Zp∗Z_{p}^{*}Zp∗​而言的,其中ppp是素数.即在在群Zp∗Z_{p}^{*}Zp∗​内,aaa是生成元,求关于xxx的方程ax=ba^x=bax=b的解, ...

  4. [模板]大步小步算法——BSGS算法

    大步小步算法用于解决:已知A, B, C,求X使得 A^x = B (mod C) 成立. 我们令x = im - j | m = ceil(sqrt(C)), i = [1, m], j = [0, ...

  5. 大步小步算法模板题, poj2417

    大步小步模板 (hash稍微有一点麻烦, poj不支持C++11略坑) #include <iostream> #include <vector> #include <c ...

  6. bzoj 4128 矩阵求逆

    /************************************************************** Problem: 4128 User: idy002 Language: ...

  7. BSGS-Junior·大步小步算法

    本文原载于:http://www.orchidany.cf/2019/02/06/BSGS-junior/#more \(\rm{0x01}\) \(\mathcal{Preface}\) \(\rm ...

  8. [BSGS]大步小步算法

    问题 BSGS被用于求解离散对数,即同余方程: \[ A^x\equiv B\pmod{P} \] 求\(x\)的最小非负整数解. 保证\(A\perp P\)(互质). 分析 首先,我们根据费马小定 ...

  9. BSGS算法(大步小步算法)

    计算\(y^x ≡ z \ mod\ p\) 中 \(x\) 的解. 这个模板是最小化了\(x\) , 无解输出\(No \ Solution!\) map<ll,ll>data; ll ...

随机推荐

  1. 孤荷凌寒自学python第八十一天学习爬取图片1

    孤荷凌寒自学python第八十一天学习爬取图片1 (完整学习过程屏幕记录视频地址在文末) 通过前面十天的学习,我已经基本了解了通过requests模块来与网站服务器进行交互的方法,也知道了Beauti ...

  2. JavaScript 数组操作方法 和 ES5数组拓展

    JavaScript中数组有各种操作方法,以下通过举例来说明各种方法的使用: 数组操作方法 push 在数组最后添加一个元素 var arr=[3,4,5,6] console.log(arr) // ...

  3. Centos6配置开启FTP Server

    vsftpd作为FTP服务器,在Linux系统中是非常常用的.下面我们介绍如何在centos系统上安装vsftp. 什么是vsftpd vsftpd是一款在Linux发行版中最受推崇的FTP服务器程序 ...

  4. css3美化radio样式

    .magic-radio{ position: absolute; display: none; } .magic-radio + label { position: relative; displa ...

  5. nodejs在linux环境下安装更新方式

    #检查是否已经安装 rpm -qa | grep python #查版本 python #最好是重新安装 Python推荐版本( >= v2.5.0 & < 3.0.0 ),否则影 ...

  6. Java学习个人备忘录之多态

    对象的多态性 class 动物 {} class 猫 extends 动物 {} class 狗 extends 动物 {} 猫 x = new 猫();//意思是建立本类的对象 new 猫(),并通 ...

  7. 算法与数据结构3.1 stack

    ★实验任务 一天,小 L 发现了一台支持一下操作的机器: IN x:将整数 x 入栈 POP:将栈顶元素出栈 ASUB:出栈两个数,将两数差的绝对值入栈 COPY:将栈顶元素(如果有的话)复制一份,入 ...

  8. 软工冲刺-Alpha 冲刺 (3/10)

    队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 很胖,刚学,照猫画虎做了登录与注册界面. 展示GitHub ...

  9. UVALive - 6864 Strange Antennas 扫描线

    题目链接: http://acm.hust.edu.cn/vjudge/problem/87213 Strange Antennas Time Limit: 3000MS 题意 一个雷达能够辐射到的范 ...

  10. DNS域名解析协议

    一. 根域 就是所谓的“.”,其实我们的网址www.baidu.com在配置当中应该是www.baidu.com.(最后有一点),一般我们在浏览器里输入时会省略后面的点,而这也已经成为了习惯. 根域服 ...