ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

hdu3117 Fibonacci Numbers(数论+矩阵快速幂)

2021-02-01 13:03:13  阅读:192  来源: 互联网

标签:frac Matrix hdu3117 Numbers int sqrt5 Fibonacci mod


题目链接: 3117 ( Fibonacci Numbers )

位数小于 \(8\) 的可以打表直接输出。

对于位数大于 \(8\) 的,直接用大数求 \(Fibonacci\) 的第 \(n\) 项会 \(TLE\) ,因此需分别求解前 \(4\) 位和后 \(4\) 位。

后 \(4\) 位直接矩阵快速幂取模即可,参见 poj3070 Fibonacci(矩阵快速幂取模) ,或者直接打表后四位找循环节更简单,网上有博主表示第 \(1500\) 项开始出现循环。

至于前四位,需要用到 \(Fibonacci\) 数列的通项公式:

\[\begin{align} Fib_n&=\frac{1}{\sqrt{5}}[(\frac{1+\sqrt5}{2})^n-(\frac{1-\sqrt5}{2})^n] \\ &\approx \frac{1}{\sqrt{5}}(\frac{1+\sqrt5}{2})^n(n\ge0) \\ \epsilon &=\vert\frac{1}{\sqrt{5}}(\frac{1-\sqrt5}{2})^n\vert\le\frac1{\sqrt5}<\frac12 \end{align} \]

因此,\(Fibonacci\) 的第 \(n\) 项即为 \(\frac{1}{\sqrt{5}}(\frac{1+\sqrt5}{2})^n\) 四舍五入。

利用这一公式结合对数运算可直接求出第 \(n\) 个 \(Fibonacci\) 数的前四位。

/**
 * hdu3117 Fibonacci Numbers
 *
 */

#include <iostream>
#include <climits>
#include <vector>
#include <cmath>
#include <iomanip>
using namespace std;

typedef long long LL;

struct Matrix
{
    LL mod;
    vector<vector<LL> > m;
    Matrix(int row, int col, LL mod = LLONG_MAX)
    {
        this->mod = mod;
        m.resize(row, vector<LL>(col));
    }
    Matrix operator * (const Matrix &t) const
    {
        int row = m.size(), col = t.m[0].size(), cnt = m[0].size();
        Matrix res(row, col, mod);
        for (int i = 0; i < row; ++i) {
            for (int j = 0; j < col; ++j) {
                for (int k = 0; k < cnt; ++k) {
                    res.m[i][j] += m[i][k]*t.m[k][j]%mod;
                    res.m[i][j] %= mod;
                }
            }
        }
        return res;
    }
};

Matrix fastPow(Matrix a, LL b, LL mod = LLONG_MAX)
{
    int n = a.m.size();
    Matrix t(n, n, mod);
    for (int i = 0; i < n; ++i) t.m[i][i] = 1;
    while (b) {
        if (b&1) t = t*a;
        a = a*a;
        b >>= 1;
    }
    return t;
}

const int mod = 10000;

int main()
{
    // 位数小于等于8则查表直接输出
    vector<long long> f = {0, 1};
    for (int i = 2; f[i-1] < 1e8; ++i) {
        LL t = f[i-1]+f[i-2];
        if (t > 1e8) break;
        f.push_back(t);
    }

    int n;
    Matrix A(2, 2, mod);
    A.m[0][0] = A.m[0][1] = A.m[1][0] = 1;
    while (cin >> n) {
        if (n < f.size()) {
            cout << f[n] << endl;
            continue;
        }

        double res = n*log10((1+sqrt(5))/2) - log10(sqrt(5));
        res = res - (LL) res;
        res = pow(10, res);
        LL ans = res*1000;
        cout << ans << "..."
             << setw(4) << setfill('0')  // 后四位可能有前导0
             << fastPow(A, n, mod).m[0][1] << endl;
    }
    return 0;
}

标签:frac,Matrix,hdu3117,Numbers,int,sqrt5,Fibonacci,mod
来源: https://www.cnblogs.com/zbhfz/p/14356033.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有