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 = ;
int r,n,m,M;
struct _matrix
{
int mat[][];
_matrix operator * (const _matrix &b) const {
_matrix res;
for(int i=;i<;++i)
for(int j=;j<;++j)
{
int sum=;
for(int k=;k<;++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,,sizeof(mat));for(int i=;i<;++i) mat[i][i]=;}
void in() {scanf("%d%d%d%d",&mat[][],&mat[][],&mat[][],&mat[][]);}
void out() {printf("%d %d\n%d %d\n",mat[][],mat[][],mat[][],mat[][]);}
};
_matrix res[*N];
void build(int x)
{
_matrix tmp;
tmp.in();
for(x+=M;x;x>>=) res[x] *= tmp;
}
vector<int> vi;
_matrix query(int x,int y)
{
_matrix ans;
ans.clear();
vi.clear();
int l=x+M-,r=y+M+;
for(x=l,y=r;x^y^;x>>=,y>>=)//注意顺序
if(~x&) ans*=res[x^];
for(x=l,y=r;x^y^;x>>=,y>>=)
if(y&)
vi.push_back(y^);
for(int i=vi.size()-;i>=;--i)
ans *= res[vi[i]];
return ans;
}
bool fir2=;
void run()
{
if(fir2) fir2=;
else puts("");
for(M=;M<=n;M+=M);
for(int i=;i<=M+n;++i) res[i].clear();
for(int i=;i<=n;++i)
build(i);
int l,r;
bool fir=;
while(m--)
{
if(fir) fir=;
else puts("");
scanf("%d%d",&l,&r);
query(l,r).out();
}
}
int main()
{
while(scanf("%d%d%d",&r,&n,&m)!=EOF)
run();
return ;
}

ZOJ 2671 Cryptography 矩阵乘法+线段树的更多相关文章

  1. THUSCH 2017 大魔法师(矩阵乘法+线段树)

    题意 https://loj.ac/problem/2980 思路 区间修改考虑用线段树维护.由于一段区间的 \(A,B,C\) 可以表示成由原来的 \(A,B,C\) 乘上带上系数再加上某一个某个常 ...

  2. Luogu P4643 【模板】动态dp(矩阵乘法,线段树,树链剖分)

    题面 给定一棵 \(n\) 个点的树,点带点权. 有 \(m\) 次操作,每次操作给定 \(x,y\) ,表示修改点 \(x\) 的权值为 \(y\) . 你需要在每次操作之后求出这棵树的最大权独立集 ...

  3. HDU 6155 Subsequence Count(矩阵乘法+线段树+基础DP)

    题意 给定一个长度为 \(n\) 的 \(01\) 串,完成 \(m\) 种操作--操作分两种翻转 \([l,r]\) 区间中的元素.求区间 \([l,r]\) 有多少个不同的子序列. \(1 \le ...

  4. HDU 3074.Multiply game-区间乘法-线段树(单点更新、区间查询),上推标记取模

    Multiply game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  5. ZOJ 3772 Calculate the Function 线段树+矩阵

    Calculate the Function Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %ll ...

  6. codeforces750E New Year and Old Subsequence 矩阵dp + 线段树

    题目传送门 思路: 先看一个大牛的题解 题解里面对矩阵的构造已经写的很清楚了,其实就是因为在每个字符串都有固定的很多中状态,刚好可以用矩阵来表达,所以$(i,j)$这种状态可以通过两个相邻的矩阵的$m ...

  7. HDU 6155 Subsequence Count(矩阵 + DP + 线段树)题解

    题意:01串,操作1:把l r区间的0变1,1变0:操作2:求出l r区间的子序列种数 思路:设DP[i][j]为到i为止以j结尾的种数,假设j为0,那么dp[i][0] = dp[i - 1][1] ...

  8. ZOJ 3911 Prime Query(线段树)

    Prime Query Time Limit: 1 Second      Memory Limit: 196608 KB You are given a simple task. Given a s ...

  9. ZOJ 1610 Count the Color(线段树区间更新)

    描述Painting some colored segments on a line, some previously painted segments may be covered by some ...

随机推荐

  1. 【BZOJ3435】[Wc2014]紫荆花之恋 替罪点分树+SBT

    [BZOJ3435][Wc2014]紫荆花之恋 Description 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从 ...

  2. go colly proxy 代理ip 动态 ip

    package main import ( "fmt" "github.com/gocolly/colly" "github.com/gocolly/ ...

  3. substr扩展版:支持中文字符串截取

    function d_substr($str, $start=0, $length, $charset="utf-8", $suffix=true) { if(function_e ...

  4. 【题解】Counting D-sets(容斥+欧拉定理)

    [题解]Counting D-sets(容斥+欧拉定理) 没时间写先咕咕咕. vjCodeChef - CNTDSETS 就是容斥,只是难了一二三四五\(\dots \inf\)点 题目大意: 给定你 ...

  5. 【题解】[APIO2009]会议中心

    [题解][P3626 APIO2009]会议中心 真的是一道好题!!!刷新了我对倍增浅显的认识. 此题若没有第二份输出一个字典序的方案,就是一道\(sort+\)贪心,但是第二问使得我们要用另外的办法 ...

  6. MySQL——sql语句的执行顺序

    #核心知识点: 书写顺序:where——>group by——>having——>order by——>limit 许多时候在书写一些复杂的sql语句的时候,尤其是在渐进式推导 ...

  7. iOS 开发实践之 Auto Layout

    原:http://xuexuefeng.com/autolayout/?utm_source=tuicool 本文是博主 iOS 开发实践系列中的一篇,主要讲述 iOS 中 Auto Layout(自 ...

  8. 【转载】帧缓冲驱动程序分析及其在BSP上的添加

    原文地址:(四)帧缓冲驱动程序分析及其在BSP上的添加 作者:gfvvz 一.BSP修改及其分析   1. BSP中直接配置的四个寄存器 S3C6410数据手册的第14.5部分是显示控制器的编程模型部 ...

  9. C++中输出 位宽和小数点后位数 的控制

    要用到这个头文件: <iomanip> setw(x) : 表示控制输出x的位宽 setprecision(x) :表示 控制输出小数点后 x 位 cout.precision(x): 表 ...

  10. Python爬虫 —— 抓取美女图片(Scrapy篇)

    杂谈: 之前用requests模块爬取了美女图片,今天用scrapy框架实现了一遍. (图片尺度确实大了点,但老衲早已无恋红尘,权当观赏哈哈哈) Item: # -*- coding: utf-8 - ...