BZOJ 4128 Matrix BSGS+矩阵求逆
题意:链接
方法: BSGS+矩阵求逆
解析:
这题就是把Ax=B(mod C)的A和B换成了矩阵。
然而别的地方并没有修改。
所以就涉及到矩阵的逆元这个问题。
矩阵的逆元怎么求呢?
先在原矩阵后接一个单位矩阵,最好还是设右对角线
先把原矩阵进行高斯消元
且消成严格右对角线的单位矩阵的形式。
然后在消元的同一时候把单位矩阵的部分一并计算。最后单位矩阵就变成了它的逆矩阵。
这道题保证矩阵有逆
然而没有逆矩阵的情况就是高斯消元搞不成。
所以推断应该也好推断。
另外,刚刚实測本题数据。关于将矩阵的hash,直接取右下角的值即可了。太弱了数据
代码:
#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 75
#define M 140345
#define base 0
using namespace std;
int n,p;
struct Matrix
{
int map[N][N];
}A,B,ret;
struct node
{
int from,to,next;
int val;
}edge[M+10];
int cnt,head[M+10];
void init()
{
memset(head,-1,sizeof(head));
cnt=1;
}
void edgeadd(int from,int to,int val)
{
edge[cnt].from=from,edge[cnt].to=to,edge[cnt].val=val;
edge[cnt].next=head[from];
head[from]=cnt++;
}
Matrix mul(Matrix a,Matrix b)
{
memset(ret.map,0,sizeof(ret.map));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
ret.map[i][j]=(ret.map[i][j]+a.map[i][k]*b.map[k][j])%p;
return ret;
}
int quick_my(int x,int y)
{
int ret=1;
while(y)
{
if(y&1)ret=(ret*x)%p;
x=(x*x)%p;
y>>=1;
}
return ret;
}
int hash(Matrix x)
{
return x.map[n][n];
}
Matrix get_inv(Matrix x)
{
memset(ret.map,0,sizeof(ret.map));
for(int i=1;i<=n;i++)ret.map[i][i]=1;
for(int i=1;i<=n;i++)
{
int chose=-1;
for(int j=i;j<=n;j++)
if(x.map[j][i]!=0){chose=j;break;}
//if(chose==-1)
// return -1
//无解我脑补应该是这样吧。
for(int j=1;j<=n;j++)
swap(x.map[i][j],x.map[chose][j]),swap(ret.map[i][j],ret.map[chose][j]);
int inv=quick_my(x.map[i][i],p-2);
for(int j=1;j<=n;j++)
{
x.map[i][j]=x.map[i][j]*inv%p;
ret.map[i][j]=ret.map[i][j]*inv%p;
}
for(int j=1;j<=n;j++)
{
if(i==j)continue;
int pre=x.map[j][i];//一定要提前记录不然肯定会影响答案。由于这个值被改变=-=我也是脑残了。
for(int k=1;k<=n;k++)
{
x.map[j][k]=((x.map[j][k]-pre*x.map[i][k])%p+p)%p;
ret.map[j][k]=((ret.map[j][k]-pre*ret.map[i][k])%p+p)%p;
}
}
}
return ret;
}
int BSGS(Matrix A,Matrix B,int C)
{
init();
int m=(int)ceil(sqrt(C));
Matrix tmp;
memset(tmp.map,0,sizeof(tmp.map));
for(int i=1;i<=n;i++)tmp.map[i][i]=1;
for(int i=0;i<m;i++)
{
int hashtmp=hash(tmp);
int flag=1;
for(int j=head[hashtmp%M];j!=-1;j=edge[j].next)
if(edge[j].val==hashtmp){flag=0;break;}
if(flag)edgeadd(hashtmp%M,i,hashtmp);
tmp=mul(tmp,A);
}
Matrix inv=get_inv(tmp);
for(int i=0;i<=m;i++)
{
int hashB=hash(B);
for(int j=head[hashB%M];j!=-1;j=edge[j].next)
if(edge[j].val==hashB)return i*m+edge[j].to;
B=mul(B,inv);
}
return -1;
}
int main()
{
scanf("%d%d",&n,&p);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&A.map[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&B.map[i][j]);
printf("%d\n",BSGS(A,B,p));
}
BZOJ 4128 Matrix BSGS+矩阵求逆的更多相关文章
- bzoj 4128: Matrix ——BSGS&&矩阵快速幂&&哈希
题目 给定矩阵A, B和模数p,求最小的正整数x满足 A^x = B(mod p). 分析 与整数的离散对数类似,只不过普通乘法换乘了矩阵乘法. 由于矩阵的求逆麻烦,使用 $A^{km-t} = B( ...
- BZOJ 4128 Matrix ——BSGS
矩阵的BSGS. 只需要哈希一下存起来就可以了. 也并不需要求逆. #include <map> #include <cmath> #include <cstdio> ...
- BZOJ 4128: Matrix
BZOJ 4128: Matrix 标签(空格分隔): OI BZOJ 大步小步 矩阵 费马小定理 Time Limit: 10 Sec Memory Limit: 128 MB Descriptio ...
- BZOJ 4128: Matrix (矩阵BSGS)
类比整数的做法就行了 1A爽哉 #include<bits/stdc++.h> using namespace std; typedef long long LL; const int M ...
- 【题解】Matrix BZOJ 4128 矩阵求逆 离散对数 大步小步算法
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4128 大水题一道 使用大步小步算法,把数字的运算换成矩阵的运算就好了 矩阵求逆?这么基础的线 ...
- 【BZOJ】4128: Matrix
题解 学习一下矩阵求逆 就是我们考虑这个矩阵 \(AA^{-1} = I\) 我们相当于让\(A\)乘上一个矩阵,变成\(I\) 我们可以利用初等行变换(只能应用初等行变换,或只应用初等列变换) 分三 ...
- bzoj 4128 矩阵求逆
/************************************************************** Problem: 4128 User: idy002 Language: ...
- BZOJ4128: Matrix(BSGS 矩阵乘法)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 813 Solved: 442[Submit][Status][Discuss] Descriptio ...
- 【BZOJ4128】Matrix BSGS+hash
[BZOJ4128]Matrix Description 给定矩阵A,B和模数p,求最小的x满足 A^x = B (mod p) Input 第一行两个整数n和p,表示矩阵的阶和模数,接下来一个n * ...
随机推荐
- OgnlContext 源码
// Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard package ognl; import ognl.enhance.Local ...
- 【bzoj3894】文理分科 网路流
[bzoj3894]文理分科 2015年3月25日3,4002 Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班 ...
- MFC设置对话框背景和边框颜色
对于对话框,只需要重载默认的消息处理函数就行了: // 重载默认的消息处理函数,主要处理WM_MOVE WM_PAINT WM_NCPAINT WM_NCACTIVATE WM_NOTIFY这// 几 ...
- (...)ES6三点扩展运算符
扩展运算符将一个数组转为用逗号分隔的参数序列 console.log(...[a, b, c]) // a b c 用于: 1 将一个数组,变为参数序列 let add = (x, y) => ...
- JS 监听绑定和取消事件
1. 原生 JS 语言: 绑定:addEventListener(type, function, false) 取消: removeEventListener(type, function, fals ...
- IntelliJ IDEA 学习--内存设置
小伙伴们经常会发现,在开发的时候,经常遇到内存被占满,导致异常卡顿,有时候提示内存溢出,这时可以通过设置xmx来改善.不过切记最好不要超过内存的1/4 打开 IDEA 安装目录,看到有一个 bin 目 ...
- Dictionary To Dynamic
原文发布时间为:2012-12-25 -- 来源于本人的百度文章 [由搬家工具导入] public static class DictionaryExt { /// <sum ...
- 透明层提示框代替windows警告窗口方法!
原文发布时间为:2009-04-05 -- 来源于本人的百度文章 [由搬家工具导入] 有人会说,怎么网页用JavaScript会有安全提示,而其他网站上面用了JavaScript都没有安全提示,呵呵, ...
- 气象城市ID列表
气象城市ID列表 数据来源: http://cj.weather.com.cn/support/Detail.aspx?id=51837fba1b35fe0f8411b6df 记录了2574个地区,2 ...
- 開關(switch)規格中,SPDT, DPDT, 3PDT, 4PDT是什麼意思?
Reference http://blog.xuite.net/auster.lai/twblog/433393966 開關(switch)用來控制電路的開與閉,機械式的switc內部是由接點開關.彈 ...