bzoj 4128: Matrix ——BSGS&&矩阵快速幂&&哈希
题目
给定矩阵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&&矩阵快速幂&&哈希的更多相关文章
- HDU4887_Endless Punishment_BSGS+矩阵快速幂+哈希表
2014多校第一题,当时几百个人交没人过,我也暴力交了几发,果然不行. 比完了去学习了BSGS才懂! 题目:http://acm.hdu.edu.cn/showproblem.php?pid=4887 ...
- 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 ...
- BZOJ 2510: 弱题( 矩阵快速幂 )
每进行一次, 编号为x的数对x, 和(x+1)%N都有贡献 用矩阵快速幂, O(N3logK). 注意到是循环矩阵, 可以把矩阵乘法的复杂度降到O(N2). 所以总复杂度就是O(N2logK) --- ...
- BZOJ 1297: [SCOI2009]迷路 [矩阵快速幂]
Description windy在有向图中迷路了. 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1. 现在给出该有向图,你能告诉windy总共有多少种不同 ...
- ACM学习历程——HDU5015 233 Matrix(矩阵快速幂)(2014陕西网赛)
Description In our daily life we often use 233 to express our feelings. Actually, we may say 2333, 2 ...
- HDU 4965 Fast Matrix Calculation 矩阵快速幂
题意: 给出一个\(n \times k\)的矩阵\(A\)和一个\(k \times n\)的矩阵\(B\),其中\(4 \leq N \leq 1000, \, 2 \leq K \leq 6\) ...
- BZOJ 2553 AC自动机+矩阵快速幂 (神题)
思路: 我们先对所有读进来的T建一个AC自动机 因为走到一个禁忌串就需要回到根 所以呢 搞出来所有的结束点 或一下 fail指针指向的那个点 然后我们就想转移 a[i][j]表示从i节点转移到j节点的 ...
- BZOJ 4128 Matrix ——BSGS
矩阵的BSGS. 只需要哈希一下存起来就可以了. 也并不需要求逆. #include <map> #include <cmath> #include <cstdio> ...
- BZOJ 4128 Matrix BSGS+矩阵求逆
题意:链接 方法: BSGS+矩阵求逆 解析: 这题就是把Ax=B(mod C)的A和B换成了矩阵. 然而别的地方并没有修改. 所以就涉及到矩阵的逆元这个问题. 矩阵的逆元怎么求呢? 先在原矩阵后接一 ...
随机推荐
- AOP+Redis锁防止表单重复提交
确保分布式锁同时满足以下四个条件 1.互斥性.在任意时刻,只有一个客户端能持有锁 2.不会发生死锁.即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁 3.具有容错性.只要 ...
- rest_framework框架——版本控制组件
API版本控制可以用来在不同的客户端使用不同的行为.REST框架提供了大量不同的版本设计. 版本控制是由传入的客户端请求决定的,并且可基于请求URL,或者基于请求头. rest_framework 当 ...
- git clone一个仓库下的单个文件【记录】
注意:本方法会下载整个项目,但是,最后出现在本地项目文件下里只有需要的那个文件夹存在.类似先下载,再过滤. 有时候因为需要我们只想gitclone 下仓库的单个或多个文件夹,而不是全部的仓库内容,这样 ...
- [LOJ#3119][Luogu5400][CTS2019]随机立方体(容斥+DP)
https://www.cnblogs.com/cjyyb/p/10900993.html #include<cstdio> #include<algorithm> #defi ...
- [高清·非影印] Python机器学习经典实例(电子书+源码)
------ 郑重声明 --------- 资源来自网络,纯粹共享交流, 如果喜欢,请您务必支持正版!! --------------------------------------------- 下 ...
- Shell变量一览
Shell变量一览 $# Shell命令的参数个数 $$ Shell本身的进程ID $! Shell最后运行的后台进程的进程ID $? Shell最后运行的命令的退出码(返回值) $- Shell使用 ...
- ActiveMQ(一)
下载地址:http://activemq.apache.org/download.html 换数据源: ActiveMQ的独占消费
- extend Thread 和 implements Runnable
原文地址:extend Thread 和 implements Runnable 一个Thread的实例只能产生一个线程 or: 同一实例(Runnable实例)的多个线程 look: public ...
- PyTorch工具
以装饰器添加所有代码对应的tensor的信息 https://github.com/zasdfgbnm/TorchSnooper
- java后台获取微信小程序openid
一.jar包准备 1.在网盘下载 链接:https://pan.baidu.com/s/15HAAWOg_yn768g4s9IrcPg 提取码:hgj0 二.在pom文件中添加依赖 1.将外部的引入的 ...