HDU 3117 Fibonacci Numbers
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3117 Fibonacci Numbers相关的知识,希望对你有一定的参考价值。
链接:http://acm.hdu.edu.cn/showproblem.php?pid=3117
题意:
- n < 40 时不会超过8位,直接打表输出
- n ≥ 40 时:
-
- 求一个数的前四位:
- 推导公式:f(n) =\frac{1}{\sqrt{5}}[(\frac{1+\sqrt{5}}{2})^{n}(1-(\frac{1-\sqrt{5}}{1+\sqrt{5}})^{n}]
- s = d.xxx * 10^{len - 4}
- 两边取对数得 \log_{10}s = \log_{10}d.xxx + len -4
- 再得d.xxxx=10^{\log_{10}s-len+4}
- s =\frac{1}{ \sqrt{5}}*(\frac{1+\sqrt{5}}{2})^{n} (s后面的数值太小可以忽略)
- len = {\log_{10}s + 1
- 后四位:
- 矩阵相乘:\begin{bmatrix}f(n)\\f(n-1) \end{bmatrix}=\begin{bmatrix}f(1)\\f(0) \end{bmatrix}*(\begin{bmatrix}1 & 1\\ 1 & 0\end{bmatrix})^{n-1}
- 求一个数的前四位:
#include <iostream> #include <cstdio> #include <cmath> using namespace std; typedef long long LL; int fib[40]; struct mat { int m[2][2]; }; int flag; int mod = 10000; void f() { fib[0] = 0; fib[1] = 1; for(int i = 2; ; i++) { fib[i] = fib[i-1] + fib[i-2]; if(fib[i] >= pow(10, 8)) { flag = i - 1; break; } } } int prev(LL n){ return pow( 10, (log10(1 / sqrt(5.0)) + n * log10((1 + sqrt(5.0)) / 2.0) - (int)(log10(1 / sqrt(5.0)) + n * log10((1 + sqrt(5.0)) / 2.0)) + 3)); } mat multiply(mat a, mat b) { mat c; for(int i = 0; i < 2; i++) { for(int j = 0; j < 2; j++) { c.m[i][j] = 0; for(int k = 0; k < 2; k++) { c.m[i][j] += (a.m[i][k] * b.m[k][j]) % mod; c.m[i][j] %= 10000; } } } return c; } mat p = {1, 1, 1, 0}; mat q = {1, 0, 0, 1}; mat quickPower(LL n) { mat m = p, b = q; while(n) { if(n & 1) { b = multiply(b, m); } n >>= 1; m = multiply(m, m); } return b; } int main() { LL n; f(); while (~scanf("%lld", &n)) { if(n <= flag) printf("%d\n", fib[n]); else { printf("%d...%04d\n", prev(n), quickPower(n).m[0][1]); } } return 0; }
以上是关于HDU 3117 Fibonacci Numbers的主要内容,如果未能解决你的问题,请参考以下文章
HDU3117-Fibonacci Numbers(矩阵高速幂+log)