zoukankan      html  css  js  c++  java
  • ZOJ 2671 Cryptography 矩阵乘法+线段树

    B - Cryptography
    Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu

    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 n each 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
    

    题意是给出n个矩阵,编号是从1到n,再给m个查询,每个查询给定l和r,输出第l个矩阵连成到第r个矩阵的积,每次乘法操作后都要对每个数对r求余。

    思路很容易想到用线段树,保存下中间的变量,下次查询再需要用到的时候可以直接返回这一个结果,时间复杂度o(mlogn)。网络上很多这题题解了,那我就贴一个zkw版的吧。需要注意的是,矩阵乘法不满足交换律,只能第l个乘第l+1个一直乘到第r个,但是zkw的线段树,是先遇到第l个和第r个,然后遇到第l+1和r-1、l+2和r-2一直到l跟r在同一层,所以顺序要有点改变,我使用了vector,但相比起传统线段树还是时间还是少了不少。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    using namespace std;
    const int N = 30010;
    int r,n,m,M;
    struct _matrix
    {
        int mat[3][3];
        _matrix operator * (const _matrix &b) const {
            _matrix res;
            for(int i=0;i<2;++i)
            for(int j=0;j<2;++j)
            {
                int sum=0;
                for(int k=0;k<2;++k)    sum+=mat[i][k]*b.mat[k][j];
                res.mat[i][j]=sum%r;
            }
            return res;
        }
        _matrix operator *= (const _matrix &b)  {
            return *this = (*this) * b;
        }
        void clear()    {memset(mat,0,sizeof(mat));for(int i=0;i<2;++i) mat[i][i]=1;}
        void in()   {scanf("%d%d%d%d",&mat[0][0],&mat[0][1],&mat[1][0],&mat[1][1]);}
        void out()  {printf("%d %d
    %d %d
    ",mat[0][0],mat[0][1],mat[1][0],mat[1][1]);}
    };
    _matrix res[4*N];
    void build(int x)
    {
        _matrix tmp;
        tmp.in();
        for(x+=M;x;x>>=1)   res[x] *= tmp;
    }
    vector<int> vi;
    _matrix query(int x,int y)
    {
        _matrix ans;
        ans.clear();
        vi.clear();
        int l=x+M-1,r=y+M+1;
        for(x=l,y=r;x^y^1;x>>=1,y>>=1)//注意顺序
            if(~x&1) ans*=res[x^1];
        for(x=l,y=r;x^y^1;x>>=1,y>>=1)
            if(y&1)
                vi.push_back(y^1);
        for(int i=vi.size()-1;i>=0;--i)
            ans *= res[vi[i]];
        return ans;
    }
    bool fir2=1;
    void run()
    {
        if(fir2) fir2=0;
        else puts("");
        for(M=1;M<=n;M+=M);
        for(int i=0;i<=M+n;++i) res[i].clear();
        for(int i=1;i<=n;++i)
            build(i);
        int l,r;
        bool fir=1;
        while(m--)
        {
            if(fir) fir=0;
            else puts("");
            scanf("%d%d",&l,&r);
            query(l,r).out();
        }
    }
    int main()
    {
        while(scanf("%d%d%d",&r,&n,&m)!=EOF)
            run();
        return 0;
    }
  • 相关阅读:
    88. Merge Sorted Array【leetcode】算法,java将两个有序数组合并到一个数组中
    70. Climbing Stairs【leetcode】递归,动态规划,java,算法
    136. Single Number【LeetCode】异或运算符,算法,java
    605. Can Place Flowers种花问题【leetcode】
    175. Combine Two Tables【LeetCode】-LEFT JON 和RIGHT JOIN,两张表关联查询-java -sql入门
    67. Add Binary【LeetCode】
    4.1 yaml配置注入
    2.1容器功能-组件添加
    1.2自动配置
    json乱码问题全配置
  • 原文地址:https://www.cnblogs.com/someblue/p/3914170.html
Copyright © 2011-2022 走看看