No pain No gain

###### ZOJ 2671 Cryptography(矩阵线段树）

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 neach 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 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int INF=0x3f3f3f3f;
typedef long long LL;
int r,n,m;
const int maxn=30000+100;
LL a[maxn][2][2];
struct Matrix{
LL mat[2][2];
Matrix(){};
Matrix(LL x1,LL x2,LL x3,LL x4)
{
mat[0][0]=x1;mat[0][1]=x2;
mat[1][0]=x3;mat[1][1]=x4;
}
}A[maxn<<2];
Matrix mult(Matrix m1,Matrix m2)
{
Matrix ans;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
ans.mat[i][j]=0;
for(int k=0;k<2;k++)
ans.mat[i][j]=(ans.mat[i][j]+m1.mat[i][k]*m2.mat[k][j])%r;
}
}
return ans;
}
void build(int rs,int l,int r)
{
if(l==r)
{
A[rs]=Matrix(a[l][0][0],a[l][0][1],a[l][1][0],a[l][1][1]);
return ;
}
int mid=(l+r)>>1;
build(rs<<1,l,mid);
build(rs<<1|1,mid+1,r);
A[rs]=mult(A[rs<<1],A[rs<<1|1]);
}
Matrix query(int x,int y,int l,int r,int rs)
{
if(l>=x&&r<=y)
return A[rs];
int mid=(l+r)>>1;
if(y<=mid) return query(x,y,l,mid,rs<<1);
if(x>mid) return query(x,y,mid+1,r,rs<<1|1);
return mult(query(x,mid,l,mid,rs<<1),query(mid+1,y,mid+1,r,rs<<1|1));
}
int main()
{
int x,y;
int cas=0;
while(~scanf("%d%d%d",&r,&n,&m))
{
REPF(i,1,n)
scanf("%lld%lld%lld%lld",&a[i][0][0],&a[i][0][1],&a[i][1][0],&a[i][1][1]);
build(1,1,n);
while(m--)
{
if(cas) puts("");
scanf("%d%d",&x,&y);cas++;
Matrix ans=query(x,y,1,n,1);
printf("%lld %lld\n%lld %lld\n",ans.mat[0][0],ans.mat[0][1],ans.mat[1][0],ans.mat[1][1]);
}
}
}


#### 【ZOJ】2671 Cryptography 线段树

2014-09-19 10:12:33

#### zoj3772--【水题】线段树区间查询+矩阵乘法

2014-04-08 21:24:15

#### zoj 2671 Cryptography(线段树+矩阵乘法)

2012-03-25 21:04:22

#### zoj 3772 Calculate the Function（矩阵+线段树）

2015-03-09 21:12:48

#### zoj 2671 Cryptography（矩阵相乘+线段树）

2014-01-22 16:13:18

#### ZOJ 2671 （线段树+矩阵乘法）

2017-07-06 21:23:31

#### ZOJ 2671 线段树 + 矩阵区间乘积

2016-12-10 23:11:16

#### ZOJ 3635 线段树

2014-05-15 14:36:43

#### zoj 1610 Count the Colors(线段树，成段更新染色)

2012-11-15 12:54:09

#### ZOJ1006解题报告

2012-03-03 16:22:17

## 不良信息举报

ZOJ 2671 Cryptography(矩阵线段树）