HDU 3117 Fibonacci Numbers(斐波那契数列通项+矩阵快速幂)

大意:

8位及以下的fib直接输出,8位以上的输出XXXX(fib前四位)...XXXX(fib后四位)。

思路:

8位以下的打表输出就好了。

fib的前四位可以利用通项公式fn=1/√5/*[(1+√5)^n/2)-(1-√5)^n/2]来求,利用对数知识求解。

例如:

log(2335566)=log(2.335566)+2.

那么log(2.335566)是log(2335566)的小数部分。

然后将log(2.335566)变为10的指数,

那么前四位就是所得的数在<10000时x10所得数的整数部分。

fib的后四位有两种求法,一是循环找出后四位的规律得到循环解,二是通过变换矩阵((1,1),(1,0))+矩阵快速幂求解。

#include <iostream>
#include <math.h>
#include <stdio.h>
#include <string.h>
using namespace std;

struct matrix
{
    int a[11][11];
    void clear()
    {
        memset(a,0,sizeof(a));
    }
    void clear1()
    {
        for(int i=0; i<11; i++)
            a[i][i]=1;

    }
    void zhuanzhi()
    {
        a[0][0]=1;
        a[0][1]=1;
        a[1][0]=1;
        a[1][1]=0;
    }
} danw,zhuan;

matrix mul(matrix a,matrix b,int n,int mod)
{
    matrix ans;
    ans.clear();
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++)
        {
            for(int k=0; k<n; k++)
            {
                ans.a[i][j]+=(a.a[i][k]%mod*b.a[k][j]%mod)%mod;
                ans.a[i][j]%=mod;
            }
        }
    //ans.n=n;
    return ans;
}
matrix Qmod(int k,matrix a,int mod,int n)
{
    matrix ans=danw;
    while(k)
    {
        if(k&1)
            ans=mul(ans,a,n,mod);
        k>>=1;
        a=mul(a,a,n,mod);
    }
    return ans;
}

int main()
{
    const double geng5=sqrt(5);
    int a[40];
    a[0]=0,a[1]=1;
    zhuan.zhuanzhi();
    danw.clear1();
    for(int i=2;i<40;i++)
    {
        a[i]=a[i-1]+a[i-2];
        //cout<<a[i]<<" "<<i<<endl;
    }
    int n;
    while(cin>>n)
    {
        if(n<=39)
         cout<<a[n]<<endl;
        else
        {
            double b=log10(1/geng5)+(double)n*log10((1+geng5)/2);
            b=b-floor(b);
            b=pow(10,b);

            while(b<1000)
             b*=10;
            matrix ans=Qmod(n,zhuan,10000,2);
            printf("%d...%04d\n",(int)b,ans.a[1][0]);
        }
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值