Question link:
Http://acm.hdu.edu.cn/showproblem.php? PID = 1, 4471
Question meaning:
Evaluate F (n ).
When N is a special point NK
Solution:
When X is not a special point, use the basic matrix to quickly calculate the power of F [X]. when X is a special point, use another matrix and perform left-side shift.
That is to say, according to the special point NK, 1-N is divided into many sections, one Section and one special point are calculated back and forth.
Two optimizations:
1. Because the rapid power of the same matrix needs to be used multiple times, the 2 k power of the matrix is pre-processed first, and each interval is calculated without any need, calculate the 2k power of the matrix.
2. When the matrix is multiplied, K is used as the primary control element to calculate a [I] [k] * A [k] [J] at a time. when a [I] [k] is 0, it jumps out directly.
Note:
Select the matrix size and position.
C1 C2 C3... ct f (n-1) f (N)
1 0 0 .. 0 f (n-2) f (n-1)
0 1 0 .. 0 f (n-3) f (n-2)
0 0 1... 0 ......
.................
0 0 0 .. 1 0 f (n-t) f (n-t + 1)
Not much.
The code is explained in detail:
# Include <iostream> # include <cmath> # include <cstdio> # include <cstdlib> # include <string> # include <cstring> # include <algorithm> # include <vector> # include <map> # include <set> # include <stack> # include <list> # include <queue> # define EPS 1e-6 # define INF 0x1f1f1f1f # define PI ACOs (-1.0) # define ll _ int64 # define lson L, M, (RT <1) # define rson m + 1, R, (RT <1) | 1 using namespace STD; # define maxn 110 # define M 1000000007/* freopen ("d ATA. in "," r ", stdin); freopen (" data. out "," W ", stdout); * // The basic idea of this question is not difficult to think of. It is mainly about detail optimization // learn the concise writing method struct Mar {int row, Col; int s [maxn] [maxn]; void Init (int A, int B) {ROW = A, Col = B; memset (S, 0, sizeof (s) ;}}; Mar operator * (const Mar & A, const Mar & B) {Mar res; Res. init (. row, B. COL); // initialize for (int K = 1; k <=. col; k ++) // uses column vectors as the standard. When there are more than 0 values, the time complexity can be reduced. {// write for (INT I = 1 in the future; I <= res. row; I ++) {if (. s [I] [k] = 0) continue; (Int J = 1; j <= res. col; j ++) {If (B. s [k] [J] = 0) continue; Res. s [I] [J] = (1ll *. s [I] [k] * B. s [k] [J] + Res. s [I] [J]) % m; // when enumerating K, it is possible to be 0} // forcibly convert to LL type, otherwise it exceeds}/* For (INT I = 1; I <= res. row; I ++) for (Int J = 1; j <= res. col; j ++) for (int K = 1; k <=. col; k ++) res. s [I] [J] = (1ll *. s [I] [k] * B. s [k] [J] + Res. s [I] [J]) % m; */return res;} Mar Ba, SP [maxn], ANS, PP [35]; // PP [I] indicates that ba ^ (2 * I) is a pre-processed matrix, so that int NN [maxn], TT [maxn], M, N, q, T, POS [maxn]; // pair The following table sorts void getpp () {PP [0] = BA; For (INT I = 1; I <= 31; I ++) // 10 ^ 9 up to 2 ^ 31 Power PP [I] = PP [I-1] * PP [I-1];} bool CMP (int A, int B) // sort the subscript to avoid moving every time. In particular, it is a waste of time {return NN [a] <NN [B];} void CAL (int) // A indicates the number of times, and the matrix is quickly idempotent. Another write form is {for (INT I = 0; I <= 31; I ++) {If (A & (1 <I) ans = PP [I] * ans;} return;}/* void CAL (int A) // write it in TLE, because each section has to calculate the power of the matrix again, the above idea is used. {Mar TMP = BA; while (a) {If (A & 1) ans = TMP * ans; A = A> 1; TMP = TMP * TMP ;}}*/ Int main () {int CA = 0; while (scanf ("% d", & N, & M, & Q )! = EOF) {memset (ans. s, 0, sizeof (ANS); For (INT I = m; I> = 1; I --) scanf ("% d", & ANS. s [I] [1]); // start with M scanf ("% d", & T); memset (BA. s, 0, sizeof (BA. s); For (INT I = 1; I <= T; I ++) // scanf ("% d", & Ba. s [1] [I]); // scanf ("% d", & Q); For (INT I = 1; I <= Q; I ++) {pos [I] = I; scanf ("% d", & NN [I], & TT [I]); memset (SP [I]. s, 0, sizeof (SP [I]. s); For (Int J = 1; j <= TT [I]; j ++) scanf ("% d", & SP [I]. s [1] [J]);} int max = t; for (INT I = 1; I <= Q; I ++) max = max (max, TT [I]); // find Ba FOR THE MAXIMUM table length. row = BA. col = max; ans. row = max, ans. col = 1; for (INT I = 2; I <= BA. row; I ++) // construct the basic matrix Ba. s [I] [I-1] = 1; getpp (); For (INT I = 1; I <= Q; I ++) {SP [I]. row = Sp [I]. col = max; For (Int J = 2; j <= Sp [I]. row; j ++) // construct the matrix SP [I] in a special position. s [J] [J-1] = 1;} Sort (Pos + 1, POS + 1 + Q, CMP); // sort NN by subscript int last = m; for (INT I = 1; I <= Q; I ++) {int P = POS [I]; // locate if (NN [p]> N | NN [p] <= last) // do not calculate continue; CAL (NN [p]-last-1 ); ans = Sp [p] * ans; // calculate last = nn [p];} CAL (n-last); printf ("case % d: % d \ n ", ++ ca, ans. s [1] [1]);} return 0 ;}