变形斐波那契数列的和 I
题目大意
就是求函数 F i = F i − 2 + F i − 1 + n + 1 F_i=F_{i-2}+F_{i-1}+n+1 Fi=Fi−2+Fi−1+n+1 前 n n n 项的和。
思路
我们可以根据求这个函数的某一项和求斐波那契数列前几项的和这两道题,把题目结合起来。
先是 1 × 5 1\times 5 1×5 的矩阵:
1(F[n-2]) | 1(F[n-1]) | 3(每次加的n) | 1(每次加的1) | 1(Q[n-2]) |
---|
然后转移矩阵 5 × 5 5\times 5 5×5:
0 | 1 | 0 | 0 | 0 |
---|---|---|---|---|
1 | 1 | 0 | 0 | 1 |
0 | 1 | 1 | 0 | 0 |
0 | 1 | 1 | 1 | 0 |
0 | 0 | 0 | 0 | 1 |
然后其他都跟之前一样。
代码
#include<cstdio>
#define mo 1000000007
#define ll unsigned long long
using namespace std;
struct matrix {
ll n, m, a[5][5];
}a, b, ans, re;
ll n;
matrix operator *(matrix x, matrix y) {
re.n = x.n;
re.m = y.m;
for (ll i = 0; i < re.n; i++)
for (ll j = 0; j < re.m; j++)
re.a[i][j] = 0;
for (ll k = 0; k < x.m; k++)
for (ll i = 0; i < re.n; i++)
for (ll j = 0; j < re.m; j++)
re.a[i][j] = (re.a[i][j] + (x.a[i][k] * y.a[k][j]) % mo) % mo;
return re;
}
void jzksm(ll now) {
b = a;
now--;
while (now) {
if (now & 1) b = b * a;
a = a * a;
now /= 2;
}
}
int main() {
scanf("%lld", &n);
if (n == 1) {
printf("1");
return 0;
}
ans.n = 1;
ans.m = 5;
ans.a[0][0] = 1;
ans.a[0][1] = 1;
ans.a[0][2] = 3;
ans.a[0][3] = 1;
ans.a[0][4] = 1;
a.n = 5;
a.m = 5;
a.a[1][0] = 1;
a.a[0][1] = 1;a.a[1][1] = 1;a.a[2][1] = 1;a.a[3][1] = 1;
a.a[2][2] = 1;a.a[3][2] = 1;
a.a[3][3] = 1;
a.a[1][4] = 1;a.a[4][4] = 1;
jzksm(n - 1);
ans = ans * b;
printf("%lld", ans.a[0][4]);
fclose(stdin);
fclose(stdout);
return 0;
}