ZOJ 2671 Cryptography(矩阵线段树)

来源:互联网 发布:php文件上传大小限制 编辑:程序博客网 时间:2024/05/02 04:24

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

InputOutput
3 4 40 10 02 11 20 00 21 00 21 42 31 32 2
0 20 00 20 10 10 02 11 2

题意:每次让你计算一个区间里(2*2)矩阵的值

分析:我们对于每个点建一个矩阵线段树,然后就是push一下,区间统计

#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
原创粉丝点击