1. 程式人生 > >hdu-1568斐波那契數列通項公式的應用

hdu-1568斐波那契數列通項公式的應用

2007年到來了。經過2006年一年的修煉,數學神童zouyu終於把0到100000000的Fibonacci數列 
(f[0]=0,f[1]=1;f[i] = f[i-1]+f[i-2](i>=2))的值全部給背了下來。 
接下來,CodeStar決定要考考他,於是每問他一個數字,他就要把答案說出來,不過有的數字太長了。所以規定超過4位的只要說出前4位就可以了,可是CodeStar自己又記不住。於是他決定編寫一個程式來測驗zouyu說的是否正確。

Input

輸入若干數字n(0 <= n <= 100000000),每個數字一行。讀到檔案尾。

Output

輸出f[n]的前4個數字(若不足4個數字,就全部輸出)。

對於資料範圍很大,位數大於四位的在f[21]的時候就到了。題目要求前四位。說實話沒有想法,雖然知道斐波那切數列但是不知道他還有通項公式。自己比較菜;在百度上找到了這個公式:

可是如何求得前四位呢,又不會了;這裡又考察了對數的性質。

在這裡有一個證明很好的部落格https://blog.csdn.net/niushuai666/article/details/7013352

然後就是程式碼了:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pi acos(-1)
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define Bor(i, a, b) for(int (i) = (b); (i) >= (a); (i) --)
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define eps 1e-7
using namespace std;
typedef long long ll;
const int maxn = 1e8;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-10;
const ll mod = 1e9 + 7;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
inline int read(){
    int ret=0,f=0;char ch=getchar();
    while(ch>'9'||ch<'0') f^=ch=='-',ch=getchar();
    while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
    return f?-ret:ret;
}
ll f[maxn];
ll n;
void init(){
	f[0] = 0;
	f[1] = 1;
	for(int i =2; i < 21; i ++){
		f[i] = f[i-1] + f[i-2];
	}
	return ;
}
int main(){
	ios::sync_with_stdio(false);
	init();
	while(cin >> n){
		if(n < 21){
			cout << f[n] << endl;
		}else{
			double t = -0.5*log(5.0)/log(10.0) + ((double)n)*log((sqrt(5.0)+1.0)/2.0)/log(10.0);
			t -= floor(t);
			t = pow(10.0, t);
			while(t < 1000){
				t *= 10;
			}
			cout << (int)t << endl;
		}
	}
	return 0;
}

繼續加油: