题目

给定矩阵A, B和模数p,求最小的正整数x满足 A^x = B(mod p).

分析

与整数的离散对数类似,只不过普通乘法换乘了矩阵乘法。

由于矩阵的求逆麻烦,使用 $A^{km-t} = B(mod \ p)$ 形式的BSGS。

然后就是判断矩阵是否相等,

一种方法是对矩阵进行Hash,

这里为了防止两个不同矩阵的Hash值冲突,使用了两个底数进行Hash。

#include<bits/stdc++.h>
using namespace std; typedef long long ll;
typedef unsigned long long ull;
const ull base1 = , base2 = ; struct matrix
{
int r, c;
int mat[][];
ull h1, h2;
matrix(){
memset(mat, , sizeof(mat));
h1 = h2 = ; //记得初始化
} void Hash()
{
for(int i = ;i < r;i++)
for(int j = ;j < c;j++)
h1 = h1 * base1 + mat[i][j], h2 = h2 * base2 + mat[i][j];
}
};
int n, p;
matrix A, B; matrix mul(matrix A, matrix B) //矩阵相乘
{
matrix ret;
ret.r = A.r; ret.c = B.c;
for(int i = ;i < A.r;i++)
for(int k = ;k < A.c;k++)
for(int j = ;j < B.c;j++)
{
ret.mat[i][j] = (ret.mat[i][j] + A.mat[i][k] * B.mat[k][j]) % p;
}
return ret;
} matrix mpow(matrix A, int n)
{
matrix ret;
ret.r = A.r; ret.c = A.c;
for(int i = ;i < ret.r;i++) ret.mat[i][i] = ;
while(n)
{
if(n & ) ret = mul(ret, A);
A = mul(A, A);
n >>= ;
}
return ret;
} map<pair<ull, ull>, int>mp;
int BSGS(matrix A, matrix B, int p)
{
int m=sqrt(p)+;mp.clear();
matrix res= B;
for(int i = ;i < m;i++)
{
res.Hash();
mp[make_pair(res.h1, res.h2)] = i;
res = mul(A, res);
}
matrix mi = mpow(A, m);
matrix tmp = mi;
for(int i = ;i <= m+;i++)
{
tmp.Hash();
pair<ull, ull> pa = make_pair(tmp.h1, tmp.h2);
if(mp.count(pa)) return i*m - mp[pa];
tmp = mul(tmp, mi);
}
} void debug_print(matrix a)
{
for(int i = ;i < a.r;i++)
{
for(int j = ;j < a.c;j++){
printf("%d ", a.mat[i][j]);
}
printf("\n");
}
} int main()
{
//srand(NULL);
scanf("%d%d", &n, &p);
A.r = A.c = n;
for(int i = ;i < n;i++)
for(int j = ;j < n;j++){
int tmp;
scanf("%d", &tmp);
A.mat[i][j] = tmp;
}
B.r = B.c = n;
for(int i = ;i < n;i++)
for(int j = ;j < n;j++){
int tmp;
scanf("%d", &tmp);
B.mat[i][j] = tmp;
} ///debug_print(A);
//debug_print(B);
//debug_print(R); printf("%d\n", BSGS(A, B, p));
}

另一种方法是随机产生一个n*1的矩阵f,若A*f=B*f我们则认为这两个矩阵是相等的。为了让直接map矩阵,还要写比较函数(奇怪的是,答案还受比较函数的影响)。

注意矩阵的左乘和右乘。

#include<bits/stdc++.h>
using namespace std; typedef long long ll;
struct matrix
{
int r, c;
int mat[][];
matrix(){
memset(mat, , sizeof(mat));
} bool operator < (const matrix &w) const //???为什么会影响结果呢
{
for (int i=;i< r;i++)
if (mat[i][]<w.mat[i][]) return ;
else if (mat[i][]>w.mat[i][]) return ;
return ;
}
};
int n, p;
matrix A, B, R; //R是随机矩阵 matrix mul(matrix A, matrix B) //矩阵相乘
{
matrix ret;
ret.r = A.r; ret.c = B.c;
for(int i = ;i < A.r;i++)
for(int k = ;k < A.c;k++)
for(int j = ;j < B.c;j++)
{
ret.mat[i][j] = (ret.mat[i][j] + A.mat[i][k] * B.mat[k][j]) % p;
}
return ret;
} matrix mpow(matrix A, int n)
{
matrix ret;
ret.r = A.r; ret.c = A.c;
for(int i = ;i < ret.r;i++) ret.mat[i][i] = ;
while(n)
{
if(n & ) ret = mul(ret, A);
A = mul(A, A);
n >>= ;
}
return ret;
} map<matrix, int>mp;
int BSGS(matrix A, matrix B, matrix R, int p)
{
int m=sqrt(p)+;mp.clear();
matrix res=mul(B, R);
for(int i = ;i < m;i++)
{
mp[res] = i;
res = mul(A, res);
}
matrix mi = mpow(A, m);
matrix tmp = mi;
for(int i = ;i <= m+;i++)
{
matrix t = mul(tmp, R);
if(mp.count(t)) return i*m - mp[t];
tmp = mul(tmp, mi);
}
} void debug_print(matrix a)
{
for(int i = ;i < a.r;i++)
{
for(int j = ;j < a.c;j++){
printf("%d ", a.mat[i][j]);
}
printf("\n");
}
} int main()
{
//srand(NULL);
scanf("%d%d", &n, &p);
A.r = A.c = n;
for(int i = ;i < n;i++)
for(int j = ;j < n;j++){
int tmp;
scanf("%d", &tmp);
A.mat[i][j] = tmp;
}
B.r = B.c = n;
for(int i = ;i < n;i++)
for(int j = ;j < n;j++){
int tmp;
scanf("%d", &tmp);
B.mat[i][j] = tmp;
} R.r = n, R.c = ;
for(int i = ;i < n;i++) R.mat[i][] = rand()%(p-) + p; ///debug_print(A);
//debug_print(B);
//debug_print(R); printf("%d\n", BSGS(A, B, R, p));
}

参考链接:

1. SFN1036 zoj 4128:Matrix BSGS+矩阵乘法

2. GXZlegend【bzoj4128】Matrix 矩阵乘法+Hash+BSGS

bzoj 4128: Matrix ——BSGS&&矩阵快速幂&&哈希的更多相关文章

  1. HDU4887_Endless Punishment_BSGS+矩阵快速幂+哈希表

    2014多校第一题,当时几百个人交没人过,我也暴力交了几发,果然不行. 比完了去学习了BSGS才懂! 题目:http://acm.hdu.edu.cn/showproblem.php?pid=4887 ...

  2. hdu4965 Fast Matrix Calculation 矩阵快速幂

    One day, Alice and Bob felt bored again, Bob knows Alice is a girl who loves math and is just learni ...

  3. BZOJ 2510: 弱题( 矩阵快速幂 )

    每进行一次, 编号为x的数对x, 和(x+1)%N都有贡献 用矩阵快速幂, O(N3logK). 注意到是循环矩阵, 可以把矩阵乘法的复杂度降到O(N2). 所以总复杂度就是O(N2logK) --- ...

  4. BZOJ 1297: [SCOI2009]迷路 [矩阵快速幂]

    Description windy在有向图中迷路了. 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1. 现在给出该有向图,你能告诉windy总共有多少种不同 ...

  5. ACM学习历程——HDU5015 233 Matrix(矩阵快速幂)(2014陕西网赛)

    Description In our daily life we often use 233 to express our feelings. Actually, we may say 2333, 2 ...

  6. HDU 4965 Fast Matrix Calculation 矩阵快速幂

    题意: 给出一个\(n \times k\)的矩阵\(A\)和一个\(k \times n\)的矩阵\(B\),其中\(4 \leq N \leq 1000, \, 2 \leq K \leq 6\) ...

  7. BZOJ 2553 AC自动机+矩阵快速幂 (神题)

    思路: 我们先对所有读进来的T建一个AC自动机 因为走到一个禁忌串就需要回到根 所以呢 搞出来所有的结束点 或一下 fail指针指向的那个点 然后我们就想转移 a[i][j]表示从i节点转移到j节点的 ...

  8. BZOJ 4128 Matrix ——BSGS

    矩阵的BSGS. 只需要哈希一下存起来就可以了. 也并不需要求逆. #include <map> #include <cmath> #include <cstdio> ...

  9. BZOJ 4128 Matrix BSGS+矩阵求逆

    题意:链接 方法: BSGS+矩阵求逆 解析: 这题就是把Ax=B(mod C)的A和B换成了矩阵. 然而别的地方并没有修改. 所以就涉及到矩阵的逆元这个问题. 矩阵的逆元怎么求呢? 先在原矩阵后接一 ...

随机推荐

  1. LeetCode 653. 两数之和 IV - 输入 BST(Two Sum IV - Input is a BST)

    653. 两数之和 IV - 输入 BST 653. Two Sum IV - Input is a BST 题目描述 给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定 ...

  2. Spring中的乱码问题

    最近发现一个问题, 中文编码保存到数据库里显示正确, 打印出来却是一串问号, 然后怀疑是平台默认编码的问题, locale命令显示是UTF-8正常, 然后单独编写一个java文件, 编译然后Java命 ...

  3. (一)线性表(linear list)

    文章目录 定义 特点 ADT (abstract data type) 定义 摘抄自 维基百科 线性表(英语:Linear List)是由 n(n≥0)个 数据元素(结点)a[0],a[1],a[2] ...

  4. 解决elementui日期时间选择器提交时与后台date类型不匹配问题

    问题描述: 在前端使用elementui的日期时间选择器后,在通过axios进行提交的时候,前端控制台出现了400(数据类型不匹配的错误)的错误. <el-form-item label=&qu ...

  5. Delphi Sysem.JSON 链式写法

    链式写法有很多优点:连贯.语意集中.简洁.一气呵成.可读性强.比如要把 3.1415926 中的 59 提取为一个整数:Pi.ToString().Substring(5,2).ToInteger() ...

  6. Appium_Page object设计模式

    Page object设计模式思维,把app按页面去划分,一个页面就是一个page对象 每个页面的元素集中管理.页面上按钮操作方法单独封装 # __author__ = " Caric Le ...

  7. Shell变量一览

    Shell变量一览 $# Shell命令的参数个数 $$ Shell本身的进程ID $! Shell最后运行的后台进程的进程ID $? Shell最后运行的命令的退出码(返回值) $- Shell使用 ...

  8. Java 之 Stream 流

    Stream流 在Java 8中,得益于Lambda所带来的函数式编程,引入了一个全新的Stream概念,用于解决已有集合类库既有的弊端 一.传统遍历 1.传统集合的多步遍历代码 几乎所有的集合(如 ...

  9. excel2016打开为空白界面解决办法

    前言 excel2016打开文件为空白的界面,明显不正常. 解决方法 https://blog.csdn.net/b2345012/article/details/94134401 以上.

  10. plsql developer中如何设置sql window显示行号

    转自:https://blog.csdn.net/qq_31302091/article/details/74931828 英文版的plsql developer中,很多时候,很多功能不去用,都不知道 ...