1. 程式人生 > >[NOI2013]矩陣遊戲

[NOI2013]矩陣遊戲

題意:對於一個n行m列的矩陣,第i行第j列的元素為F[i][j]。已知a, b, c, d,並且矩陣元素滿足:
F[1][1] = 1
F[i,j] = a * F[i][j-1] + b (j!=1)
F[i,1] = c * F[i-1][m] + d (i!=1)
求F[n][m] 答案對1e9 + 7取模
1 <= n, m <= 1e1000000
1 <= a, b, c, d <= 1e9
這道題一眼看上去非常的矩陣快速冪
好像沒毛病?
看了眼資料量 哭遼
沒關係 我可以10000進位制快速冪!(看起來很穩
那就寫一寫?

// luogu-judger-enable-o2
#include <cstdlib> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <map> #pragma GCC optimize("Ofast,no-stack-protector") using namespace std; const int N = (int)1e6 + 5; const int M = 1e3; const long long P = 1e9 + 7; inline long
long Mod(long long x){ while(x >= P) x -= P; while(x < 0) x += P; return x; } struct Matrix{ long long mat[2][2]; inline void init(int aa, int ab, int ba, int bb){ mat[0][0] = aa, mat[0][1] = ab, mat[1][0] = ba, mat[1][1] = bb; } }next1, next2, stot, tot; inline Matrix operator
*(const Matrix& x, const Matrix& y){ Matrix z; z.init(0, 0, 0, 0); //printf("!!!\n"); z.mat[0][0] = Mod(z.mat[0][0] + x.mat[0][0] * y.mat[0][0] % P); z.mat[0][0] = Mod(z.mat[0][0] + x.mat[0][1] * y.mat[1][0] % P); z.mat[0][1] = Mod(z.mat[0][1] + x.mat[0][1] * y.mat[1][1] % P); z.mat[0][1] = Mod(z.mat[0][1] + x.mat[0][0] * y.mat[0][1] % P); z.mat[1][0] = Mod(z.mat[1][0] + x.mat[1][0] * y.mat[0][0] % P); z.mat[1][0] = Mod(z.mat[1][0] + x.mat[1][1] * y.mat[1][0] % P); z.mat[1][1] = Mod(z.mat[1][1] + x.mat[1][0] * y.mat[0][1] % P); z.mat[1][1] = Mod(z.mat[1][1] + x.mat[1][1] * y.mat[1][1] % P); return z; } char n[N], m[N], tn[N], tm[N]; long long a, b, c, d; inline void init(){ scanf("%s%s%lld%lld%lld%lld", n, m, &a, &b, &c, &d); next1.init(a, b, 0, 1); next2.init(c, d, 0, 1); } inline Matrix qqp(Matrix x, int y){ Matrix res; res.init(1, 0, 0, 1); while(y){ if(y & 1) res = res * x; x = x * x; y >>= 1; } return res; } inline Matrix qpow(Matrix x, int len, char* y){ int tmp; Matrix res, tt; res.init(1, 0, 0, 1); for(int i = 0; i < len; i += 4){ tmp = 0; for(int j = 3; j >= 0; --j) tmp = (tmp << 3) + (tmp << 1) + y[i + j] - '0'; tt = qqp(x, tmp); res = res * tt; x = qqp(x, 10000); } return res; } inline void debug(Matrix x){ printf("%lld %lld %lld %lld\n", x.mat[0][0], x.mat[0][1], x.mat[1][0], x.mat[1][1]); } int main(int argc, char *argv[]) { init(); int ln = strlen(n), lm = strlen(m), ltn, ltm; for(int i = ln - 1; i >= 0; --i) if(n[i] == '0') n[i] = '9'; else{n[i] = n[i] - 1; break;} for(int i = lm - 1; i >= 0; --i) if(m[i] == '0') m[i] = '9'; else{m[i] = m[i] - 1; break;} int it; for(it = 0; it < ln && n[it] == '0'; ++it); ltn = ln - it; for(; it < ln; ++it) tn[ln - it - 1] = n[it]; tn[ltn] = tn[ltn + 1] = tn[ltn + 2] = '0'; tn[ltn + 3] = '\0'; for(it = 0; it < lm && m[it] == '0'; ++it); ltm = lm - it; for(; it < lm; ++it) tm[lm - it - 1] = m[it]; tm[ltm] = tm[ltm + 1] = tm[ltm + 2] = '0'; tm[ltm + 3] = '\0'; stot = qpow(next1, ltm, tm); tot = next2 * stot; tot = stot * qpow(tot, ltn, tn); printf("%lld\n", Mod(tot.mat[0][0] + tot.mat[0][1])); return 0; }