zoukankan      html  css  js  c++  java
  • hdu 3117 Fibonacci Numbers 矩阵快速幂+公式

    斐波那契数列后四位可以用快速幂取模(模10000)算出。前四位要用公式推

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

    f(n)=(((1+√5)/2)^n+((1-√5)/2)^n)/√5

    假设F[n]可以表示成 t * 10^k(t是一个小数),那么对于F[n]取对数log10,答案就为log10 t + K,此时很明显log10 t<1,于是我们去除整数部分,就得到了log10

    再用pow(10,log10 t)我们就还原回了t。将t×1000就得到了F[n]的前四位。 具体实现的时候Log10 F[n]约等于((1+√5)/2)^n/√5,这里我们把((1-√5)/2)^n这一项忽略了,
    因为当N>=40时,这个数已经小的可以忽略。于是log10 F[n]就可以化简成log10 1/√5 + n*log10 (1+√5)/2

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    using namespace std;
    
    const int Mod = 10000;
    const int N = 4;
    int msize;
    
    struct Mat
    {
        int mat[N][N];
    };
    
    Mat operator *(Mat a, Mat b)
    {
        Mat c;
        memset(c.mat, 0, sizeof(c.mat));
        for(int k = 0; k < msize; ++k)
            for(int i = 0; i < msize; ++i)
                if(a.mat[i][k])
                    for(int j = 0; j < msize; ++j)
                        if(b.mat[k][j])
                            c.mat[i][j] = (c.mat[i][j] +a.mat[i][k] * b.mat[k][j])%Mod;
        return c;
    }
    
    Mat operator ^(Mat a, int k)
    {
        Mat c;
        memset(c.mat,0,sizeof(c.mat));
        for(int i = 0; i < msize; ++i)
            c.mat[i][i]=1;
        for(; k; k >>= 1)
        {
            if(k&1) c = c*a;
            a = a*a;
        }
        return c;
    }
    
    int a[50];
    const double sq5 = sqrt(5.0);
    
    int main()
    {
    //    freopen("in.txt","r",stdin);
        int n;
        msize = 2;
        Mat A;
        A.mat[0][0] = 1;
        A.mat[0][1] = 1;
        A.mat[1][0] = 1;
        A.mat[1][1] = 0;
        a[0] = 0;
        a[1] = 1;
        for(int i=2;i<40;i++)
            a[i] = a[i-1] + a[i-2];
        while(~scanf("%d", &n))
        {
            if(n<40) printf("%d
    ",a[n]);
            else
            {
                double t = n * log10((1.0 + sq5) / 2) - log10(sq5);
                t -= (int)t;
                t = pow(10.0, t);
                printf("%d...",(int)(t * 1000));
                Mat aa = A;
                aa = aa ^ (n-1);
                printf("%04d
    ",aa.mat[0][0]);
            }
        }
        return 0;
    }
  • 相关阅读:
    js弹出遮罩层
    委托集合使用
    C#动态属性(.NET Framework4.5支持)
    ABP项目启动及源代码结构
    ABP项目概述
    Visual Studio 2017调试开源项目代码
    GIT的前世今生
    近期上海面试总结(二)
    近期上海面试总结(一)
    一个基于反射的消息发布订阅模型详解
  • 原文地址:https://www.cnblogs.com/pach/p/7231061.html
Copyright © 2011-2022 走看看