描述
题解
一看到这道题题目,第一感觉是错别字,因为fei
打成fu
也不是不可能。然而一细看,发现真的是浮。但是比较直观的发现,这道题和斐波那契有些许关联。
首先,分析数据范围,十分大,一般的递推不可能过,这时可以想到,求十分大的斐波那契数时使用的方法是矩阵快速幂,那么这道题也许也适用,但是这里是浮点型,怎么解决呢?
于是乎,根据Float-Bonacci
的定义我们可以发现一个潜在条件,那就是浮点的精度只有一位,那么我们可以通过X10
使其转化为:
FB’(n) = FB’(n - 10) + FB’(n - 34)
然后求FB’(10n)即可。
这里出现的难点是单元矩阵的构造原理,我也不明白其中缘由,但是百度到一个矩阵的PPT上讲,在右上角的(n - 1) * (n - 1)
的小矩阵中的主对角线上填1,矩阵第n
行填对应的系数,其他地方都填0
即可。当然,这个矩阵颠倒一下方向什么的也未尝不可。(比如斐波那契的可以构造为0111
,也可以构造为1110
)
举一个简单的例子:
找到f(n) = 4f(n - 1) - 3f(n - 2) + 2f(n - 4)的第k项。
矩阵构造为:
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#define INF 0x3fffffff
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
ll n;
struct matrix
{
ll a[35][35];
};
matrix mu(matrix A, matrix B)
{
matrix 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] += A.a[i][k] * B.a[k][j];
t.a[i][j] %= mod;
}
}
}
return t;
}
matrix multi(matrix mat, long long x)
{
int i;
matrix 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, mat);
}
x = x >> 1;
mat = mu(mat, mat);
}
return b;
}
void input()
{
scanf("%lld", &n);
}
void solve()
{
matrix mat;
memset(mat.a, 0, sizeof(mat.a));
int i;
// 构造单元矩阵
mat.a[1][10] = mat.a[1][34] = 1;
for (i = 2; i <= 34; i++)
{
mat.a[i][i - 1] = 1;
}
// 特判n≤4
if (n <= 4)
{
puts("1");
return ;
}
// n>4
ll x = (n - 4) * 10;
matrix res = multi(mat, x);
ll ans = 0;
for (i = 1; i <= 34; i++)
{
ans = (ans + res.a[1][i]) % mod;
}
printf("%lld", ans);
}
int main()
{
input();
solve();
return 0;
}