# 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(矩阵线段树） 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)