题意:f(0) = f(1) = 1, f(n) = f(n-1) + f(n-2) + n,.对于给定的n,求出f(n)
思路:由于n < 1e9,所以没法直接递推计算。对于线性递推关系,我们可以通过矩阵的快速幂来加速乘法。
但是由于题意给出的是带n的递推式,无法直接得到只含常数的矩阵,需要对递推式变形。可以得到: f(n+3) = 2f(n+2) - f(n) +1.
所以矩阵为: 2 0 -1 1 初始的列向量为: 4
1 0 0 0 1
0 1 0 0 1
0 0 0 1 1
坑:1.由于矩阵中有负数,使结果出现负数,需要先加一个模,在除模。
2. 矩阵相乘,注意顺序。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
using namespace std;
template<class T>
inline bool read(T &n)
{
T signal = 1, x = 0;
char ch = getchar();
while((ch < '0' || ch >'9') && ch != EOF && ch != '-')
ch = getchar();
if(ch == EOF)
return false;
if(ch == '-')
signal = -1, ch = getchar();
while(ch >= '0' && ch <= '9'){
x *= 10;
x += ch - '0';
ch = getchar();
}
n = signal * x;
return true;
}
const int MAX = 101000;
const int MOD = 1000000007;
struct Matrix{
static const int MAX = 4;
int row,column;
long long a[MAX][MAX];
Matrix(int n,int m):row(n),column(m){
memset(a,0,sizeof(a));
}
Matrix operator *(const Matrix& B) const{
Matrix C(row,B.column);
for(int i = 0;i < C.row; ++i)
for(int j = 0 ;j < C.column; ++j)
for(int k = 0 ; k < column; ++k)
C.a[i][j] = (C.a[i][j] + (a[i][k] * B.a[k][j]) %MOD + MOD) %MOD;
return C;
}
Matrix qpow(int n){
Matrix C(row,column);
for(int i = 0 ;i < C.column; ++i)
C.a[i][i] = 1;
Matrix B = *this;
while(n){
if(n & 1)
C = C * B;
B = B * B;
n >>= 1;
}
return C;
}
};
int main(void)
{
int T;
scanf("%d", &T);
while(T--){
int n;
scanf("%d", &n);
if(n == 0 || n == 1)
printf("1\n");
else{
Matrix A(4,1);
A.a[0][0] = 4;
A.a[1][0] = 1;
A.a[2][0] = 1;
A.a[3][0] = 1;
Matrix B(4,4);
B.a[0][0] = 2;
B.a[0][2] = -1;
B.a[0][3] = B.a[1][0] = B.a[2][1] = B.a[3][3] = 1;
B = B.qpow(n-2);
Matrix C = B * A;
printf("%lld\n",C.a[0][0]);
}
}
return 0;
}