TengBieBie已经学习了很多关于斐波那切数列的性质,所以他感到一些些厌烦。现在他遇到了一个新的数列,这个数列叫做Float-Bonacci。这里有一个关于Float-Bonacci的定义。
对于一个具体的n,TengBieBie想要快速计算FB(n).
但是TengBieBie对FB的了解非常少,所以他向你求助。
你的任务是计算FB(n).FB(n)可能非常大,请输出FB(n)%1,000,000,007 (1e9+7)即可。
Input
输入共一行,在一行中给出一个整数n (1<=n<=1,000,000,000)。
Output
对于每一个n,在一行中输出FB(n)%1,000,000,007 (1e9+7)。
Input示例
5
Output示例
2
原递推等价于G(n)=G(n-10)+G(n-34)。然后对于一个n,求G(10n)。
记录一下这个题是因为其矩阵的构造,之前求斐波那契f(n)=f(n-1)+f(n-2)知道要去构造一个1110的矩阵,然后快速幂 从而降低时间复杂度。但是对于这个题目来说,在纸上划了一些遍之后。。。还是不知道对于G(n)=G(n-10)+G(n-34)怎样构造矩阵,感觉智商捉急。
看了题解才知道
no.a[1][10] = no.a[1][34] = 1;
for (i = 2; i <= 34; i++)
{
no.a[i][i - 1] = 1;
}
这样构造矩阵,G(n) G(n-1)一直到G(n-34)。很巧妙的构造方法。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
#define INF 0x3fffffff
const int mod = 1e9 + 7;
ll n;
struct matr {
ll a[35][35];
};
matr mu(matr no1, matr no2)
{
matr t;
memset(t.a, 0, sizeof(t.a));
int i, j, k;
for (i = 1; i <= 34; i++)
{
for (j = 1; j <= 34; j++)
{
for (k = 1; k <= 34; k++)
{
t.a[i][j] += no1.a[i][k] * no2.a[k][j];
t.a[i][j] %= mod;
}
}
}
return t;
}
matr multi(matr no, long long x)
{
int i, j;
matr b;
memset(b.a, 0, sizeof(b.a));
for (i = 1; i <= 34; i++)
{
b.a[i][i] = 1;
}
while (x)
{
if (x & 1)
{
b = mu(b, no);
}
x = x >> 1;
no = mu(no, no);
}
return b;
}
void input()
{
scanf("%lld", &n);
}
void solve()
{
matr no;
memset(no.a, 0, sizeof(no.a));
int i, j;
no.a[1][10] = no.a[1][34] = 1;
for (i = 2; i <= 34; i++)
{
no.a[i][i - 1] = 1;
}
if (n <= 4)
{
puts("1");
return;
}
ll x = (n - 4) * 10;
matr res = multi(no, x);
ll ans = 0;
for (i = 1; i <= 34; i++)
{
ans = (ans + res.a[1][i]) % mod;
}
printf("%lld", ans);
}
int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout);
input();
solve();
return 0;
}