AcDream 1078 递推数 嵌套循环节+矩阵快速幂
题意:已知A0 = 0 , A1 = 1 , An = 3 * An - 1 + An - 2 (n >= 2). 求 AAAAN Mod (1e9 + 7) (也就是A[A[A[A[N]]]])。
解法:标程竟然使用set+pair来寻找循环节,并且第一次循环节长达222222224,不知道内存要吃掉多少。由于是一个嵌套的定义,因此要找出每一层的循环节,最终推出最内层的循环节为240,次之为183120,再之222222224,最后就是1e9+7了。通过矩阵快速幂求解第x项还是飞快的,注意当某一层为0时最后的结果就为0了。
代码如下:
#include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; typedef long long int int64; const int mod[4] = {240, 183120, 222222224, 1000000007}; int MOD; struct Matrix { int64 mat[2][2]; void reset() { mat[0][0] = 3, mat[1][0] = 1; mat[0][1] = 1, mat[1][1] = 0; } void unit() { mat[0][0] = 1, mat[1][0] = 0; mat[0][1] = 0, mat[1][1] = 1; } void init() { memset(mat, 0, sizeof (mat)); } friend int64 pow(Matrix & a, int b); friend Matrix operator * (const Matrix & a, const Matrix & b); }; int64 pow(Matrix & a, int64 b) { Matrix ret; ret.unit(); while (b) { if (b & 1) ret = ret * a; a = a * a; b >>= 1; } return ret.mat[0][0]; } Matrix operator * (const Matrix & a, const Matrix & b) { Matrix ret; ret.init(); for (int i = 0; i < 2; ++i) for (int j = 0; j < 2; ++j) for (int k = 0; k < 2; ++k) { ret.mat[i][j] += (a.mat[i][k] * b.mat[k][j]) % MOD; ret.mat[i][j] %= MOD; } return ret; } void solve(int64 x) { for (int i = 0; i < 4; ++i) { Matrix mm; mm.reset(); MOD = mod[i]; if (x > 0) { x = pow(mm, x-1); } else x = 0; } printf("%lld\n", x); } int main() { int T; int64 N; scanf("%d", &T); while (T--) { scanf("%lld", &N); solve(N); } return 0; }