洛谷p1939矩阵加速
链接:https://www.luogu.org/problemnew/show/P1939
题目描述
a[1]=a[2]=a[3]=1
a[x]=a[x-3]+a[x-1] (x>3)
求a数列的第n项对1000000007(10^9+7)取余的值。
输入输出格式
输入格式:
第一行一个整数T,表示询问个数。
以下T行,每行一个正整数n。
输出格式:
每行输出一个非负整数表示答案。
输入输出样例
输入样例
3
6
8
10
输出样例
4
9
19
说明
对于30%的数据 n<=100;
对于60%的数据 n<=210^7;
对于100%的数据 T<=100,n<=210^9;
/*
由a[1]=a[2]=a[3]=1;
a[x]=a[x-3]+a[x-1] (x>3)
=a[x-1]*1+a[x-2]*0+a[x-3]*1
a[x-1]=a[x-1]*1+a[x-2]*0+a[x-3]*0;
a[x-2]=a[x-1]*0+a[x-2]*1+a[x-3]*0;
所以单位矩阵就可以设置为
1 0 1
1 0 0
0 1 0
剩下的就是矩阵快速幂的模板
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<queue>
#include<cmath>
#include<stack>
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
ll n;
struct mat{
ll m[3][3];
}unit;
mat operator* (mat a, mat b){//重载乘号
mat res;
ll x;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++){
x = 0;
for (int k = 0; k < 3; k++)
x += (a.m[i][k] * b.m[k][j]) % mod;
res.m[i][j] = x%mod;
}
return res;
}
void init_unit(){//初始化单位向量
memset(unit.m, 0, sizeof unit.m);
unit.m[0][0] = 1;
unit.m[0][2] = 1;
unit.m[1][0] = 1;
unit.m[2][1] = 1;
}
mat pow_quick(ll n){//矩阵快速幂
mat res=unit;
if (n < 0) return res;
while (n){
if (n & 1) res = res*unit;
unit = unit*unit;
n >>= 1;
}
return res;
}
int main(){
int t; cin >> t;
while (t--){
cin >> n;
init_unit();
mat res = pow_quick(n - 2);
cout << res.m[0][0] * 1 << endl;
}
return 0;
}