传送门: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. 浅谈JS-cookie,你是香甜可口的小点心吗?

    引言: 想必大家一定听过或看过浏览器cookie,早在nokia雄霸天下.我们还不太明白浏览器的时候,cookie就已经悄悄地存在于浏览器的“设置选项”中了.当时它的用途仅仅是让你选择是否“清除”.年 ...

  2. HTMLTestRunner带饼图

    # -*- coding: utf-8 -*- """ A TestRunner for use with the Python unit testing framewo ...

  3. MarkDown编辑器使用

    有几款好用的MarkDown编辑器,参考: https://blog.csdn.net/bat67/article/details/72804251 我就下载的是 MarkDown 2来使用. 现用现 ...

  4. [问题] docker: Failed to start Docker Application Container Engine.

    docker无法启动: # systemctl restart docker Job for docker.service failed because the control process exi ...

  5. 策略模式,ASP.NET实现

    策略模式,ASP.NET实现 using System; using System.Collections.Generic; using System.Linq; using System.Web; ...

  6. CodeForces - 792C Divide by Three (DP做法)

    C. Divide by Three time limit per test: 1 second memory limit per test: 256 megabytes input: standar ...

  7. OSG学习:使用已有回调示例

    回调的类型有很多种,一般很容易就想到的是UpdateCallBack,或者EventCallBack,回调的意思就是说,你可以规定在某件事情发生时启动一个函数,这个函数可能做一些事情.这个函数就叫做回 ...

  8. ASP.NET 使用MVC4的EF5 Code First 入门(一):创建数据库

    一.基本流程 建立模型→建立控制器→EF框架自动生成视图的数据库 二.基本理论 1.约定优于配置(Convention Over Configuration) 设计不好的框架通常需要多个配置文件,每一 ...

  9. mysql 时区问题:The server time zone value '???ú±ê×??±??' is unrecognized

    org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java.sql.SQLE ...

  10. Sass的命令编译

    [Sass]命令编译 命令编译是指使用你电脑中的命令终端,通过输入 Sass 指令来编译 Sass.这种编译方式是最直接也是最简单的一种方式.因为只需要在你的命令终端输入: 单文件编译: sass & ...