B-Cryptography
Time limit:5000 Ms
Memory limit:32768kb
64bit Io format:% LLD & % maid status practice zoj 2671
Description
Young cryptoanalyst Georgie is planning to break the new cipher specified ted by his friend Andie. To do this, he must make some linear transformations over the ringZR = z/Rz.
Each linear transformation is defined2 × 2Matrix. Georgie has a sequence of MatricesA1, A2,...,. As a step of his algorithm he must take some segmentAI, AI + 1,..., AJOf the sequence and multiply some vector by a productPi, j = ai x ai + 1 X... x AJOf the segment. He must do itMVarious segments.
Help Georgie to determine the products he needs.
Inputthere are several test cases in the input. The first line of each case contains
R(
1 & lt; = R & lt; = 10,000),
N(
1 <= n <= 30,000) And
M(
1 <= m <= 30,000). Next
NBlocks of two lines, containing two integer numbers ranging from
0To
R-1Each, describe matrices. blocks are separated with blank lines. They are followed
MPairs of integer numbers ranging from
1To
NEach that describe segments, products for which are to be calculated.
There is an empty line between cases. Output
PrintMBlocks containing two lines each. Each line shoshould contain two integer numbers ranging from0ToR-1And define the corresponding product matrix.
There shoshould be an empty line between cases.
Separate blocks with an empty line.
Sample
Input |
Output |
3 4 40 10 02 11 20 00 21 00 21 42 31 32 2 |
0 20 00 20 10 10 02 11 2 |
N matrices are given, ranging from 1 to n, and then M queries are given. Each query is given L and R, and the product of the L matrix is output to the R matrix, after each multiplication operation, R is required for each number.
The idea is easy to think of using a line segment tree to save the variable in the middle. This result can be directly returned when the next query is necessary, with time complexity O (mlogn ). There are a lot of questions on the Internet, so I will post a zkw version. It should be noted that matrix multiplication does not meet the exchange law, and only the L + 1 of the 1st can be multiplied to the r of the 1st, but the zkw line segment tree, is first met L and R, then met L + 1 and R-1, L + 2 and R-2 until l with R in the same layer, so the order needs to change a bit, I have used vector, but it is much less time than the traditional line segment tree.
Code
# 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 re S;} _ 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", & mat [0] [0], & mat [0] [1], & mat [1] [0], & mat [1] [1]);} void out () {printf ("% d \ n", 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;} ve Ctor <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) // pay attention to the sequence 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", & L, & R); query (L, R ). out () ;}} int Mai N () {While (scanf ("% d", & R, & N, & M )! = EOF) Run (); Return 0 ;}