# ZOJ 2671 Cryptography(矩阵线段树）

334人阅读 评论(0)

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]);
}
}
}


0
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：280199次
• 积分：7344
• 等级：
• 排名：第2985名
• 原创：436篇
• 转载：1篇
• 译文：0篇
• 评论：39条
友链
阅读排行