关闭

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

题意:每次让你计算一个区间里(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

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