ZOJ 2671 Cryptography 矩阵乘法+线段树
Time Limit:5000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu
Description
Young cryptoanalyst Georgie is planning to break the new cipher invented by his friend Andie. To do this, he must make some linear transformations over the ring Zr = Z/rZ.
Each linear transformation is defined by 2×2 matrix. Georgie has a sequence of matrices A1 , A2 ,..., An . As a step of his algorithm he must take some segment Ai , Ai+1 , ..., Aj of the sequence and multiply some vector by a product Pi,j=Ai × Ai+1 × ... × Aj of the segment. He must do it for m various segments.
Help Georgie to determine the products he needs.
Input
There are several test cases in the input. The first line of each case contains r ( 1 <= r <= 10,000), n ( 1 <= n <= 30,000) and m ( 1 <= m <= 30,000). Next n blocks of two lines, containing two integer numbers ranging from 0 to r - 1 each, describe matrices. Blocks are separated with blank lines. They are followed by m pairs of integer numbers ranging from 1 to n each that describe segments, products for which are to be calculated.
There is an empty line between cases.
Output
Print m blocks containing two lines each. Each line should contain two integer numbers ranging from 0 to r - 1 and define the corresponding product matrix.
There should be an empty line between cases.
Separate blocks with an empty line.
Sample
| Input | Output |
3 4 4 |
0 2 |
题意是给出n个矩阵,编号是从1到n,再给m个查询,每个查询给定l和r,输出第l个矩阵连成到第r个矩阵的积,每次乘法操作后都要对每个数对r求余。
思路很容易想到用线段树,保存下中间的变量,下次查询再需要用到的时候可以直接返回这一个结果,时间复杂度o(mlogn)。网络上很多这题题解了,那我就贴一个zkw版的吧。需要注意的是,矩阵乘法不满足交换律,只能第l个乘第l+1个一直乘到第r个,但是zkw的线段树,是先遇到第l个和第r个,然后遇到第l+1和r-1、l+2和r-2一直到l跟r在同一层,所以顺序要有点改变,我使用了vector,但相比起传统线段树还是时间还是少了不少。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int N = ;
int r,n,m,M;
struct _matrix
{
int mat[][];
_matrix operator * (const _matrix &b) const {
_matrix res;
for(int i=;i<;++i)
for(int j=;j<;++j)
{
int sum=;
for(int k=;k<;++k) sum+=mat[i][k]*b.mat[k][j];
res.mat[i][j]=sum%r;
}
return res;
}
_matrix operator *= (const _matrix &b) {
return *this = (*this) * b;
}
void clear() {memset(mat,,sizeof(mat));for(int i=;i<;++i) mat[i][i]=;}
void in() {scanf("%d%d%d%d",&mat[][],&mat[][],&mat[][],&mat[][]);}
void out() {printf("%d %d\n%d %d\n",mat[][],mat[][],mat[][],mat[][]);}
};
_matrix res[*N];
void build(int x)
{
_matrix tmp;
tmp.in();
for(x+=M;x;x>>=) res[x] *= tmp;
}
vector<int> vi;
_matrix query(int x,int y)
{
_matrix ans;
ans.clear();
vi.clear();
int l=x+M-,r=y+M+;
for(x=l,y=r;x^y^;x>>=,y>>=)//注意顺序
if(~x&) ans*=res[x^];
for(x=l,y=r;x^y^;x>>=,y>>=)
if(y&)
vi.push_back(y^);
for(int i=vi.size()-;i>=;--i)
ans *= res[vi[i]];
return ans;
}
bool fir2=;
void run()
{
if(fir2) fir2=;
else puts("");
for(M=;M<=n;M+=M);
for(int i=;i<=M+n;++i) res[i].clear();
for(int i=;i<=n;++i)
build(i);
int l,r;
bool fir=;
while(m--)
{
if(fir) fir=;
else puts("");
scanf("%d%d",&l,&r);
query(l,r).out();
}
}
int main()
{
while(scanf("%d%d%d",&r,&n,&m)!=EOF)
run();
return ;
}
ZOJ 2671 Cryptography 矩阵乘法+线段树的更多相关文章
- THUSCH 2017 大魔法师(矩阵乘法+线段树)
题意 https://loj.ac/problem/2980 思路 区间修改考虑用线段树维护.由于一段区间的 \(A,B,C\) 可以表示成由原来的 \(A,B,C\) 乘上带上系数再加上某一个某个常 ...
- Luogu P4643 【模板】动态dp(矩阵乘法,线段树,树链剖分)
题面 给定一棵 \(n\) 个点的树,点带点权. 有 \(m\) 次操作,每次操作给定 \(x,y\) ,表示修改点 \(x\) 的权值为 \(y\) . 你需要在每次操作之后求出这棵树的最大权独立集 ...
- HDU 6155 Subsequence Count(矩阵乘法+线段树+基础DP)
题意 给定一个长度为 \(n\) 的 \(01\) 串,完成 \(m\) 种操作--操作分两种翻转 \([l,r]\) 区间中的元素.求区间 \([l,r]\) 有多少个不同的子序列. \(1 \le ...
- HDU 3074.Multiply game-区间乘法-线段树(单点更新、区间查询),上推标记取模
Multiply game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- ZOJ 3772 Calculate the Function 线段树+矩阵
Calculate the Function Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %ll ...
- codeforces750E New Year and Old Subsequence 矩阵dp + 线段树
题目传送门 思路: 先看一个大牛的题解 题解里面对矩阵的构造已经写的很清楚了,其实就是因为在每个字符串都有固定的很多中状态,刚好可以用矩阵来表达,所以$(i,j)$这种状态可以通过两个相邻的矩阵的$m ...
- HDU 6155 Subsequence Count(矩阵 + DP + 线段树)题解
题意:01串,操作1:把l r区间的0变1,1变0:操作2:求出l r区间的子序列种数 思路:设DP[i][j]为到i为止以j结尾的种数,假设j为0,那么dp[i][0] = dp[i - 1][1] ...
- ZOJ 3911 Prime Query(线段树)
Prime Query Time Limit: 1 Second Memory Limit: 196608 KB You are given a simple task. Given a s ...
- ZOJ 1610 Count the Color(线段树区间更新)
描述Painting some colored segments on a line, some previously painted segments may be covered by some ...
随机推荐
- struts2中拦截器与过滤器之间的区别
首先是一张经典的struts2原理图 当接收到一个httprequest , a) 当外部的httpservletrequest到来时 b) 初始到了servlet容器 传递给一个标准的过滤器链 c) ...
- Django项目高频使用文件
数据库配置: MySQL数据库 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': 'localhost' ...
- jxl java工具类,导出excel,导入数据库
1: 引入jxl jar 我使用的为maven管理, <!--Excel工具--> <dependency> <groupId>net.sourceforge.je ...
- spring运行步骤
Spring确实使你能通过最简单可行的解决的方法来解决你的问题. 而这是有有非常大价值的.同一时候他的源码的设计理念也受到非常多程序猿的追捧,简洁,易用.但是从哪着手研究Spring却是非常多新手头疼 ...
- 转载 j2ee j2se j2me 区别,mvc 和ssh联系理解
[转]J2SE J2EE J2ME的区别 以及 MVC与SSH对应关系 2014-3-6阅读322 评论0 J2SE J2EE J2ME的区别多数编程语言都有预选编译好的类库以支持各种特定的功能,在J ...
- (转)source insight 窗口嵌入
昨天用了一下source insight ,都说很强大,也有感觉,但是这个强大的东西往往不是那么容易弄清楚的,或者一下子就好上手的,工具强大,功能复杂多样,一开始不知道怎么入手,以后慢慢来吧,学习是要 ...
- Ubuntu PPPoE拨号上网指定网卡
Just follow these steps: Check that the ethernet cable is properly connected Open Terminal Run sudo ...
- Java for LeetCode 098 Validate Binary Search Tree
Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...
- DOM相关操作的案例
1 . 模态框案例 示例 : 打开网页时有一个普通的按钮,点击当前按钮显示一个背景图,中心并弹出一个弹出框,点击X的时候会关闭当前的模态框 <!DOCTYPE html> <htm ...
- 20145239 《Java程序设计》第5周学习总结
20145239 <Java程序设计>第5周学习总结 教材学习内容总结 (一)掌握try...catch...finally处理异常的方法: 程序中有许多意想不到的错误,所以我们要学会一些 ...