【发布时间】:2015-08-28 13:56:40
【问题描述】:
我正在尝试解决这个问题:SPOJ problem。
经过一些研究,我发现它归结为对第 n 个 fib 数的简单计算,但是 n 可能会变得非常大,因此 O(n) 解决方案不会有任何好处。谷歌搜索,我发现你可以计算出 O(logn) 中的第 n 个 fib 数,还有一个代码示例可以做到这一点:
long long fibonacci(int n) {
long long fib[2][2] = {{1,1},{1,0}}, ret[2][2] = {{1,0},{0,1}}, tmp[2][2] = {{0,0},{0,0}};
int i, j, k;
while (n) {
if (n & 1) {
memset(tmp, 0, sizeof tmp);
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
for (k = 0; k < 2; k++)
tmp[i][j] = (tmp[i][j] + ret[i][k] * fib[k][j]);
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
ret[i][j] = tmp[i][j];
}
memset(tmp, 0, sizeof tmp);
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
for (k = 0; k < 2; k++)
tmp[i][j] = (tmp[i][j] + fib[i][k] * fib[k][j]);
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
fib[i][j] = tmp[i][j];
n /= 2;
}
return (ret[0][1]);
}
我尝试针对问题对其进行修改,但仍然收到 WA:http://ideone.com/3TtE5m
我计算模运算是否错误?还是有其他问题?
【问题讨论】:
-
斐波那契或素数?
-
对于 SPOJ 问题,使用 fib(n+1),除了 n = 0,我不确定 0 个硬币算不算 1 way。请注意, (x%12345678901) * y(%12345678901) 最多需要 68 位。在 64 位模式下,可以实现一个基于汇编的函数来对模 12345678901 进行乘法运算,因为乘法和除法之后的乘积可以是 128 位。