B - 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 1
0 0 2 1
1 2 0 0
0 2 1 0
0 2 1 4
2 3
1 3
2 2
0 2
0 0 0 2
0 1 0 1
0 0 2 1
1 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 矩阵乘法+线段树的更多相关文章

  1. THUSCH 2017 大魔法师(矩阵乘法+线段树)

    题意 https://loj.ac/problem/2980 思路 区间修改考虑用线段树维护.由于一段区间的 \(A,B,C\) 可以表示成由原来的 \(A,B,C\) 乘上带上系数再加上某一个某个常 ...

  2. Luogu P4643 【模板】动态dp(矩阵乘法,线段树,树链剖分)

    题面 给定一棵 \(n\) 个点的树,点带点权. 有 \(m\) 次操作,每次操作给定 \(x,y\) ,表示修改点 \(x\) 的权值为 \(y\) . 你需要在每次操作之后求出这棵树的最大权独立集 ...

  3. HDU 6155 Subsequence Count(矩阵乘法+线段树+基础DP)

    题意 给定一个长度为 \(n\) 的 \(01\) 串,完成 \(m\) 种操作--操作分两种翻转 \([l,r]\) 区间中的元素.求区间 \([l,r]\) 有多少个不同的子序列. \(1 \le ...

  4. HDU 3074.Multiply game-区间乘法-线段树(单点更新、区间查询),上推标记取模

    Multiply game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  5. ZOJ 3772 Calculate the Function 线段树+矩阵

    Calculate the Function Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %ll ...

  6. codeforces750E New Year and Old Subsequence 矩阵dp + 线段树

    题目传送门 思路: 先看一个大牛的题解 题解里面对矩阵的构造已经写的很清楚了,其实就是因为在每个字符串都有固定的很多中状态,刚好可以用矩阵来表达,所以$(i,j)$这种状态可以通过两个相邻的矩阵的$m ...

  7. 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] ...

  8. ZOJ 3911 Prime Query(线段树)

    Prime Query Time Limit: 1 Second      Memory Limit: 196608 KB You are given a simple task. Given a s ...

  9. ZOJ 1610 Count the Color(线段树区间更新)

    描述Painting some colored segments on a line, some previously painted segments may be covered by some ...

随机推荐

  1. python 基础 7.6 sys 模块

    一.sys 模块 sys 模块主要功能是获取参数     [root@www pythonscripts]# cat 2.py #!/usr/bin/python #coding=utf-8   im ...

  2. python 基础 6.2 raise 关键字使用

    一. raise 关键字    raise 用来触发异常    语法如下:     raise[Exception [,args [,traceback]]]     语句中Exception 是异常 ...

  3. RTSP转RTMP-HLS网页无插件视频直播-EasyNVR功能介绍-音频开启

    EasyNVR简介 EasyNVR能够通过简单的摄像机通道配置.存储配置.云平台对接配置.CDN配置等,将统监控行业里面的高清网络摄像机IP Camera.NVR.移动拍摄设备接入到EasyNVR,E ...

  4. 关于mongodb创建索引的一些经验总结(转)

    查看语句执行计划: explain() 在mongodb3+版本后输出格式发生改变: 详情参见:https://docs.mongodb.com/v3.0/reference/method/curso ...

  5. PHP 格式化数字串

    在xls或csv文件中, 超过12位以上的数字会被"科学计数", 所以当php读取这些文件的时候, 会读成 420E+16 , 显然这不是我们想要的, 所以就要用到数字格式化了! ...

  6. 获取原生的DOM方式,DIY脚手架,vue-cli的使用

    一 . 获取原生的DOM的方式 在js中,我们可以通过id, class 或者标签获取DOM元素,vue中也为我们提供了获取原生DOM的方法,就是给标签或者组件添加 ref 属性,通过 this.$r ...

  7. CodeForces - 540C Ice Cave —— BFS

    题目链接:https://vjudge.net/contest/226823#problem/C You play a computer game. Your character stands on ...

  8. 应用程序无法启动(0*c000007b)

    2个插件就解决  一个是DX缺失工具检查那个 一个是运行库缺失检查

  9. XML文件的特点

    1.这个东西的规则比较简单,并且人眼看起来也比较容易理解,结构上也比较好操作,并且并无与任何编程语言绑定. 所以,很多编程语言就都为XML这个东西编写了读写XML的库,所以XML看起来所谓的通用,其实 ...

  10. python之tkinter_2

    关于tkinter的组件介绍,这篇博客很详细: https://www.cnblogs.com/aland-1415/p/6849193.html tkinter is to make interfa ...