题意:
给n个方块排成一列,仙子阿用红蓝绿黄四种颜色的油漆给他们染色。
求染成红色的方块和绿色的方块的个数同时为偶数的染色方案的个数,输出对10007取余的结果。
n <= 1e9.
解析:
推出递推式子,然后用矩阵快速幂解决。
P202.
主要是这个矩阵快速幂写的太漂亮了。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1
using namespace std;
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);
const int mod = 10007;
typedef vector<int> vec;
typedef vector<vec> mat;
mat mul(mat &A, mat &B)
{
mat C(A.size(), vec(B[0].size()));
for (int i = 0; i < A.size(); i++)
{
for (int k = 0; k < B.size(); k++)
{
for (int j = 0; j < B[0].size(); j++)
{
C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
}
}
}
return C;
}
mat pow(mat A, LL n)
{
mat B(A.size(), vec(A.size()));
for (int i = 0; i < A.size(); i++)
{
B[i][i] = 1;
}
while (0 < n)
{
if (n & 1)
B = mul(B, A);
A = mul(A, A);
n >>= 1;
}
return B;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int ncase;
scanf("%d", &ncase);
while (ncase--)
{
LL n;
scanf("%lld", &n);
mat A(3, vec(3));
A[0][0] = 2; A[0][1] = 1; A[0][2] = 0;
A[1][0] = 2; A[1][1] = 2; A[1][2] = 2;
A[2][0] = 0; A[2][1] = 1; A[2][2] = 2;
A = pow(A, n);
printf("%d\n", A[0][0]);
}
return 0;
}