數論-hdu3117題解

題目鏈接

題目大意:輸出 Fibonacci 數列的第 n 項 an,如果 an 位數 ≤8 ,否則按格式“高四位…低四位”輸出。

分析:注意點:題目給的 n 的範圍是 [0, 108] ,直接使用遞推的方式求 an 會超時,並且數值超出了表示範圍(C++)。

首先Fibonacci 數列的 0~39 項的位數都是在 8 位以內的,如果不知道,可以觀察測試用例,a39 對應 63245986 , a40 對應 1023…4155 。所以,對於 0~39 項,可以通過遞推公式先打表。

然後,先考慮取出高四位。
Fibonacci 數列有如下的通項公式:
通項公式
對通項公式進行變換(兩邊取對數)得到下面的表達式:
在這裏插入圖片描述
以10爲底取對數的好處在於,如果將大數用科學計數法的形式表示,例如 123456789123456789 。就可以寫成 1.23456789123456789x1017 , 進一步可以寫成 log10(1.23456789123456789)+17 這種小數加整數的形式,即 log10(123456781456789) = log10(1.23456789123456789)+17 ,如果想得到高四位,就是將 10log10(1234.56789123456789)向下取整即可,而 log10(1234.56789123456789) = log10(1.23456789123456789)+3 ,就和log10(123456789123456789) 建立了聯繫。按照這種思路,一個大數的高四位就容易得到了。

對於低四位,取模就可以,但是因爲遞推會超時,所以需要用到下面的性質:
在這裏插入圖片描述
這樣就是矩陣快速冪+取模,在找到對應位置的值就可以了。

代碼:

#include<bits/stdc++.h>
using namespace std;
typedef struct{
    int a[2][2];
}MATRIX;

const int mod = 10000;
MATRIX a, ans;
int k;
int f[40];

void init(){
    f[1] = 1;
    f[2] = 1;
    for(int i=3; i<40; i++){
        f[i] = f[i-1] + f[i-2];
    }
}

MATRIX mult(MATRIX a, MATRIX b){
    MATRIX tmp;
    for(int i=0; i<2; i++){
        for(int j=0; j<2; j++){
            tmp.a[i][j] = ((a.a[i][0]*b.a[0][j])%mod + (a.a[i][1]*b.a[1][j])%mod)%mod;
        }
    }
    return tmp;
}

MATRIX fastPow(MATRIX m, int n){
    MATRIX res;
    for(int i=0; i<2; i++){
        res.a[i][0] = res.a[i][1] = 0;
        res.a[i][i] = 1;
    }
    while(n){
        if(n&1) res = mult(res, a);
        a = mult(a, a);
        n >>= 1;
    }
    return res;
}

int head(int n){
    double t=-0.5*log10(5.0)+(double)n*log10((1+pow(5.0,0.5))/2);
    t=t-floor(t);  //獲得小數部分
    double x=pow(10,t+3);  //還原
    return (int)floor(x);  //得到整數部分
}

int main(){
    init();
    while(~scanf("%d", &k)){
        if(k<40) printf("%d\n", f[k]);
        else{
            a.a[0][0] = 0;
            a.a[0][1] = a.a[1][0] = a.a[1][1] = 1;
            printf("%d...", head(k));
            ans = fastPow(a, k-1);
            printf("%04d\n", ans.a[1][1]);
        }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章