首页 > 代码库 > hdu1568&&hdu3117 求斐波那契数前四位和后四位

hdu1568&&hdu3117 求斐波那契数前四位和后四位

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1568

题意:如标题所示,求斐波那契数前四位,不足四位直接输出答案

斐波那契数列通式:技术分享

当n<=20的时候,不足四位,所以直接打表。

当n>20的时候,大于四位的时候,ans满足这个公式:ans=-0.5*log10(5.0)+num*1.0*log10((1+sqrt(5.0))/2.0);                                                                                                                                                        

这个公式是怎么来的呢?我们可以对an取10的对数,根据对数的性质。                                                                                                                                                                                                                        

log10(ans)=log10(1/sqrt(5))+log10(((1+sqrt(5))/2)^num-((1-sqrt(5))/2)^num))                                                                                                                                                                                            

log10(ans)=0-0.5*log10(5.0)+log10(((1+sqrt(5))/2)^num-((1-sqrt(5))/2)^num)),当num趋于无穷的的时候  。

lim((1-sqrt(5))/2)^num)=0                                                                                                              

log10(ans)=0-0.5*log10(5.0)+log10(((1+sqrt(5))/2)^num)= -0.5*log10(5.0)+num*1.0*log10( (1+sqrt(5))/2),我们就得到了上文的公式。                                                                                                          

这里说一下原理,x=123456789,那么y=log10(x)=1.23456789,这个时候将y*=1000,就得到了 y=1234.56789,求幂次和取对数互为逆运算,通过这个原理我们可以求前x的长度。   

//Author: xiaowuga
#include <bits/stdc++.h>
#define maxx INT_MAX
#define minn INT_MIN
#define inf 0x3f3f3f3f
#define maxn 
using namespace std;
typedef long long ll;
ll table[21];
int main() {
    ios::sync_with_stdio(false);cin.tie(0);
    table[0]=0;table[1]=1;
    for(int i=2;i<=20;i++) table[i]=table[i-1]+table[i-2];
    ll num;
    while(cin>>num){
       if(num<=20) cout<<table[num]<<endl;
        else{
            double ans=-0.5*log10(5.0)+num*1.0*log10((1+sqrt(5.0))/2.0);
            ans=ans-(ll)ans;
            double a=pow(10.0,ans);
            a=1000*a;
            cout<<(ll)a<<endl;
        } 
    } 
    return 0;
}

 

hdu3117:Fibonacci Numbers

这道题求斐波那契的数列的前四位和后四位,前四位和1568是一样的,后四位只需要把mod变成10000就行了,比较简单,直接看代码吧!!

//Author: xiaowuga
#include <bits/stdc++.h>
#define maxx INT_MAX
#define minn INT_MIN
#define inf 0x3f3f3f3f
#define n 2
#define MOD 10000
using namespace std;
typedef long long ll;
ll table[45];
ll first_four(ll num){
     double ans=-0.5*log10(5.0)+num*1.0*log10((1+sqrt(5.0))/2.0);
     ans=ans-(ll)ans;
     double a=pow(10.0,ans);
     a=1000*a;
     return (ll)a;
}
struct Matrix{
    ll mat[2][2];
    Matrix operator * (const Matrix & m) const{
        Matrix tmp;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++){
                tmp.mat[i][j]=0;
                for(int k=0;k<n;k++){
                    tmp.mat[i][j]+=mat[i][k]*m.mat[k][j]%MOD;
                    tmp.mat[i][j]%=MOD;
                }
            }
        return tmp;
    }
};
Matrix POW(Matrix &m,ll k){
    Matrix ans;
    memset(ans.mat,0,sizeof(ans.mat));
    for(int i=0;i<n;i++) ans.mat[i][i]=1;
    while(k){
        if(k&1) ans=ans*m;
        k/=2;
        m=m*m;
    }
    return ans;
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);
    table[0]=0;table[1]=1;
    for(int i=2;i<=39;i++) table[i]=table[i-1]+table[i-2];
    ll num;
    while(cin>>num){
       if(num<=39) cout<<table[num]<<endl;
       else{
            cout<<first_four(num)<<"...";
            Matrix m;
            memset(m.mat,0,sizeof(m.mat));
            m.mat[0][1]=m.mat[1][1]=m.mat[1][0]=1;m.mat[0][0]=0;
            Matrix ans=POW(m,num-1);
            cout.fill(0);
            cout.width(4);
            cout<<ans.mat[1][1]%MOD<<endl;
       }
    } 
    return 0;
}

 

hdu1568&&hdu3117 求斐波那契数前四位和后四位