HDU3117-Fibonacci Numbers(矩陣快速冪+log)
來源:程序員人生 發布時間:2014-09-17 00:01:04 閱讀次數:1848次
題目鏈接
題意:斐波那契數列,當長度大于8時,要輸出前四位和后四位
思路:后四位很簡單,矩陣快速冪取模,難度在于前四位的求解。
已知斐波那契數列的通項公式:f(n) = (1 / sqrt(5)) * (((1 + sqrt(5)) / 2) ^ n - ((1 + sqrt(5)) / 2) ^ n),當n >= 40時((1 + sqrt(5)) / 2) ^ n近似為0。所以我們假設f(n) = t * 10 ^ k(t為小數),所以當兩邊同時取對數時,log10(t * 10 ^ k) = log10(t) + k = log10((1 / sqrt(5)) * (((1 + sqrt(5)) / 2))) = log10(1
/ sqrt(5)) + n * log10(((1 + sqrt(5)) / 2))),然后減掉整數k,就可以得到log10(t),進而得到t值。
代碼:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
//typedef long long ll;
typedef __int64 ll;
const int MOD = 10000;
struct mat{
ll s[2][2];
mat(ll a = 0, ll b = 0, ll c = 0, ll d = 0) {
s[0][0] = a;
s[0][1] = b;
s[1][0] = c;
s[1][1] = d;
}
mat operator * (const mat& c) {
mat ans;
memset(ans.s, 0, sizeof(ans.s));
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++) {
ans.s[i][j] = (ans.s[i][j] + s[i][k] * c.s[k][j]);
if (ans.s[i][j] >= 100000000)
ans.s[i][j] %= MOD;
}
return ans;
}
}c(1, 1, 1, 0), tmp(1, 0, 0, 1);
ll n;
mat pow_mod(ll k) {
if (k == 0)
return tmp;
else if (k == 1)
return c;
mat a = pow_mod(k / 2);
mat ans = a * a;
if (k % 2)
ans = ans * c;
return ans;
}
int main() {
while (scanf("%I64d", &n) != EOF) {
if (n == 0)
printf("0
");
else {
mat ans = pow_mod(n - 1);
if (n >= 40) {
double k = log10(1.0 / sqrt(5.0)) + (double)n * log10((1.0 + sqrt(5.0)) / 2.0);
double temp = k;
temp = k - (int)temp;
printf("%d...%.4I64d
", (int)(1000.0 * pow(10.0, temp)), ans.s[0][0] % MOD);
}
else
printf("%I64d
", ans.s[0][0]);
}
}
return 0;
}
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈