题目
分析
这道题目一看就想到矩阵快速幂。可以先把
把
元素 | 值 |
---|---|
|
31 |
|
197 |
|
1255 |
|
7997 |
|
50959 |
|
324725 |
|
2069239 |
|
13185773 |
这样看去确实没有什么规律,但是转念一想,出题人一定会给我们一线生机的(队友的神想法)。题目中总共给了三个递推式,分别是
所以用矩阵快速幂求出
代码
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
typedef long long int LL;
typedef vector<LL> vec;
typedef vector<vec> mat;
const int MOD = 1e9 + 7;
mat mul(mat A, mat B)
{
mat C(A.size(), vec(B[0].size()));
for (unsigned i = 0; i < A.size(); i++)
for (unsigned j = 0; j < B[0].size(); j++)
for (unsigned k = 0; k < B.size(); k++)
C[i][j] = (C[i][j] + A[i][k] * B[k][j] + MOD) % MOD; // 中间会出现负数,所以要先+MOD。
return C;
}
mat pow(mat A, LL n)
{
mat B(A.size(), vec(A.size()));
for (unsigned i = 0; i < A.size(); i++)
B[i][i] = 1;
while (n > 0)
{
if (n & 1) B = mul(B, A);
A = mul(A, A);
n >>= 1;
}
return B;
}
int main()
{
//freopen("test.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int T;
scanf("%d", &T);
while (T--)
{
LL n;
scanf("%I64d", &n);
if (n == 2)
{
printf("31\n");
continue;
}
else if (n == 3)
{
printf("197\n");
continue;
}
else if (n == 4)
{
printf("1255\n");
continue;
}
mat M1(3, vec(3));
M1[0][0] = 4;M1[0][1] = 17;M1[0][2] = -12;
M1[1][0] = 1;M1[1][1] = 0;M1[1][2] = 0;
M1[2][0] = 0;M1[2][1] = 1;M1[2][2] = 0;
mat M2(3, vec(1));
M2[0][0] = 1255;
M2[1][0] = 197;
M2[2][0] = 31;
mat ans = mul(pow(M1, n - 4), M2);
printf("%I64d\n", ans[0][0]);
}
return 0;
}