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\n", most, low);
}
int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    init();
    while (cin >> n) work();
    return 0;
}

时间: 2024-10-16 15:45:58

HDU 3117 Fibonacci Numbers 数学的相关文章

hdu 3117 Fibonacci Numbers

点击此处即可传送到hdu 3117 **Fibonacci Numbers** Problem Description The Fibonacci sequence is the sequence of numbers such that every element is equal to the sum of the two previous elements, except for the first two elements f0 and f1 which are respectively

HDU 3117 Fibonacci Numbers(斐波那契前后四位,打表+取对+矩阵快速幂)

HDU 3117 Fibonacci Numbers(斐波那契前后四位,打表+取对+矩阵快速幂) ACM 题目地址:HDU 3117 Fibonacci Numbers 题意: 求第n个斐波那契数的前四位和后四位. 不足8位直接输出. 分析: 前四位有另外一题HDU 1568,用取对的方法来做的. 后四位可以用矩阵快速幂,MOD设成10000就行了. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * Blog: http://blog.csdn.

HDU 3117 Fibonacci Numbers(矩阵快速幂+公式)

题目地址:HDU 3117 对于后四位可以用矩阵快速幂快速求出来,但前四位就没办法了.要知道斐波那契数列是有通项公式的,所以只能通过通项公式来求前四位,但公式不能求后四位,因为公式使用浮点数求的,精度显然不够,求前四位要用到对数. 通项公式为: f(n)=1/sqrt(5)(((1+sqrt(5))/2)^n+((1-sqrt(5))/2)^n) 假设F[n]可以表示成 t * 10^k(t是一个小数),那么对于F[n]取对数log10,答案就为log10 t + K,此时很明显log10 t<

HDU 3117 Fibonacci Numbers(Fibonacci矩阵加速递推+公式)

题目意思很简单:求第n个Fibonacci数,如果超过八位输出前四位和后四位中间输出...,否则直接输出Fibonacci数是多少. 后四位很好求,直接矩阵加速递推对10000取余的结果就是. 前四位搜了一下:http://blog.csdn.net/xieqinghuang/article/details/7789908 Fibonacci的通项公式,对,fibonacci数是有通项公式的-- f(n)=1/sqrt(5)(((1+sqrt(5))/2)^n+((1-sqrt(5))/2)^n

HDU - 3117 Fibonacci Numbers 矩阵快速幂 + 取大数前4位

题目大意:要求输出第n个fibonacci数,如果该数超过1e9,就输出该数的前4位和后四位 解题思路:通过打表可得,第40个fibonacci数是大于1e9的,所以40之前的可以直接计算 40之后的比较麻烦,参考了别人的题解 http://blog.sina.com.cn/s/blog_9bf748f301019q3t.html #include<cstdio> #include<cmath> using namespace std; typedef long long ll;

UVA 11582 Colossal Fibonacci Numbers! 数学

n比较小,最多n*n就回出现循环节.... Colossal Fibonacci Numbers! Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Problem F: Colossal Fibonacci Numbers! The i'th Fibonacci number f (i) is recursively defined in the

HDU 5018 Revenge of Fibonacci(数学)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5018 Problem Description In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation Fn = Fn-1 + Fn-2 with seed values F1 = 1; F2 = 1 (sequence A000045 in OEIS). ---

codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论+线段树)

In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation F1 = 1; F2 = 1; Fn = Fn - 1 + Fn - 2 (n > 2). DZY loves Fibonacci numbers very much. Today DZY gives you an array consisting of n integers: a1, a2, ...,

HDU - 1848 - Fibonacci again and again

先上题目: Fibonacci again and again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4964    Accepted Submission(s): 2072 Problem Description 任何一个大学生对菲波那契数列(Fibonacci numbers)应该都不会陌生,它是这样定义的:F(1)=1;F