您的位置:首页 > 其它

51Nod-1358-浮波那契

2016-09-12 16:46 225 查看
ACM模版

描述



题解

一看到这道题题目,第一感觉是错别字,因为
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  矩阵快速幂