Tisuama

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

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


阅读更多
个人分类: 线段树 矩阵专题
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

ZOJ 2671 Cryptography(矩阵线段树)

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭