zoukankan      html  css  js  c++  java
  • HDU 3117 Fibonacci Numbers 数学

    http://acm.hdu.edu.cn/showproblem.php?pid=3117

    fib是有一个数学公式的。

    这里的是标准的fib公式

    那么fib = 1 / sqrt(5) * ((1 + sqrt(5) / 2) ^ n - ((1 - sqrt(5)) / 2)^n) = 1 / sqrt(5) * (A^n - B^n)

    那么,求后4位可以直接矩阵快速幂。

    不能用上面公式的快速幂取模,因为存在精度误差。

    然后求前4位的话,就是一个套路公式了。

    在上一篇博客。http://www.cnblogs.com/liuweimingcprogram/p/6583154.html

    这里因为后面的B很小,所以可以忽略。如果不忽略的话,就没办法做了。

    比如你取A得前4位,减去B的前4位,那肯定错。比如123456789的前4位是1234,而1234的前4位又是1234,那么相减就等于0了。不过这里B的小数,前4位也是0.

    然后还要除以sqrt(5),这个时候就需要你保留前5位,除以sqrt(5)后,再保留4位。

    不然的话,比如你取了前4位是1234,除以sqrt(5),只剩下3位了。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    const int maxn = 4;
    struct Matrix {
        LL a[maxn][maxn];
        int row;
        int col;
    };
    struct Matrix matrix_mul  (struct Matrix a, struct Matrix b, int MOD) {  //求解矩阵a*b%MOD
        struct Matrix c = {0};  //这个要多次用到,栈分配问题,maxn不能开太大,
        //LL的时候更加是,空间是maxn*maxn的,这样时间用得很多,4和5相差300ms
        c.row = a.row; //行等于第一个矩阵的行
        c.col = b.col; //列等于第二个矩阵的列
        for (int i = 1; i <= a.row; i++) { //枚举第一个矩阵的行
            for (int j = 1; j <= b.col; j++) { //枚举第二个矩阵的列,其实和上面数值一样
                for (int k = 1; k <= b.row; k++) { //b中的一列中,有“行”个元素 notice
                    c.a[i][j] += a.a[i][k] * b.a[k][j];  //这里不及时取模,又有可能错!HDU 4565
                }
                c.a[i][j] = (c.a[i][j] + MOD) % MOD; //如果怕出现了负数取模的话。可以这样做
            }
        }
        return c;
    }
    struct Matrix quick_matrix_pow(struct Matrix ans, struct Matrix base, int n, int MOD) {
    //求解a*b^n%MOD
        while (n) {
            if (n & 1) {
                ans = matrix_mul(ans, base, MOD);//传数组不能乱传,不满足交换律
            }
            n >>= 1;
            base = matrix_mul(base, base, MOD);
        }
        return ans;
    }
    LL fib[222];
    void init() {
        fib[0] = 0;
        fib[1] = 1;
        for (int i = 2; i <= 40; ++i) {
            fib[i] = fib[i - 1] + fib[i - 2];
        }
    }
    int n;
    int calc(double a, LL b, int k) { //a^b的前k + 1位
        double res = b * log10(a * 1.0) - (LL)(b * log10(a * 1.0)); //获得小数部分
        return (int)(pow(10.0, k + res) / sqrt(5.0));
    }
    
    int getMost() {
        double a = (1 + sqrt(5.0)) / 2;
        int res = calc(a, n, 4);
        while (res >= 10000) res /= 10;
        return res;
    }
    int getLow() {
        struct Matrix t1 = {0};
        t1.row = 1, t1.col = 2;
        t1.a[1][1] = 1, t1.a[1][2] = 0;
    
        struct Matrix t2 = {0};
        t2.row = t2.col = 2;
        t2.a[1][1] = t2.a[1][2] = 1;
        t2.a[2][1] = 1, t2.a[2][2] = 0;
    
        struct Matrix res = quick_matrix_pow(t1, t2, n - 1, 10000);
        return res.a[1][1];
    }
    void work() {
        if (n <= 39) {
            cout << fib[n] << endl;
            return;
        }
        int most = getMost();
        int low = getLow();
        printf("%04d...%04d
    ", most, low);
    }
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        init();
        while (cin >> n) work();
        return 0;
    }
    View Code
  • 相关阅读:
    java中计算两个时间差
    增强for循环用法
    SQLServer类型与Java类型转换问题解决
    有关SQL模糊查询
    js 弹出div窗口 可移动 可关闭 (转)
    登陆sqlserver及修改端口号 (转)
    C#判断IP地址是否合法函数-使用正则表达式-2个 (转)
    c#图像处理入门(-bitmap类和图像像素值获取方法) 转
    MongoDB C#驱动中Query几个方法 (转)
    微信公众帐号自定义菜单创建及事件响应开发教程 附源代码(转)
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6587300.html
Copyright © 2011-2022 走看看