您的位置:首页 > 其它

3070 Fibonacci(O(log n)求解 )

2011-10-17 23:01 453 查看
Fibonacci序列可由此公式求出:



设a={1,1,1,0}

这样Fibonacci(n)可以由:

a^n=a^(n/2)*a^(n/2) (n是偶数)

a^n=a^((n-1)/2)*a^((n-1)/2)*a (n是奇数)

这样和快速幂乘有些相似了,可以O(logn)求出。

快速幂乘代码:

// 快速计算 (n ^ p) % m 的值
__int64 Montgomery(__int64 n, __int64 p, __int64 m)
{
__int64 r = n % m;
__int64 k = 1;
while (p > 1)
{
if ((p & 1)!=0)
{
k = (k * r) % m;
}
r = (r * r) % m;
p /= 2;
}
return (r * k) % m;
}


完整版代码:

#include<iostream>
using namespace std;

void fen(int r[][2], int k[][2]) {
int ans[2][2];
ans[0][0] = (r[0][0] * k[0][0] % 10000 + r[0][1] * k[1][0] % 10000) % 10000;
ans[0][1] = (r[0][0] * k[0][1] % 10000 + r[0][1] * k[1][1] % 10000) % 10000;
ans[1][0] = (r[1][0] * k[0][0] % 10000 + r[1][1] * k[1][0] % 10000) % 10000;
ans[1][1] = (r[1][0] * k[0][1] % 10000 + r[1][1] * k[1][1] % 10000) % 10000;
r[0][0] = ans[0][0], r[0][1] = ans[0][1], r[1][0] = ans[1][0], r[1][1] = ans[1][1];
}

int fbnq(int num) {
int k[2][2] = {1, 0, 0, 1};
int r[2][2] = {1, 1, 1, 0};
while (num > 1) {
if ((num & 1) != 0) {
fen(k, r);
}
fen(r, r);
num /= 2;
}
fen(r, k);
return r[0][1];
}

int main() {
int num;
while (cin >> num && num != -1) {
if (num == 0)
cout << 0 << endl;
else
cout << fbnq(num) << endl;
}
return 0;
}

由此公式可知:
设矩阵为{x,y,y,z} 根据Fibonacci性质可知:z=x-y;

所以这个矩阵我们每次只需计算一半

x=x*x+y*y;

y=x*y+y*(x-y);

所以有如下简洁代码:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define mod 10000
int n;

int fibonacci(int n) {
int ra, rb, a, b, x, y;
if (n < 2)return n;
ra = rb = a = b = 1;
n -= 2;
while (n) {
if (n & 1) {
x = ra * a + rb*b;
y = ra * b + rb * (a - b + mod);
ra = x % mod;
rb = y % mod;
}
n >>= 1;
x = a * a + b*b;
y = (2 * a + mod) * b - b*b;
a = x % mod;
b = y % mod;
}
return ra;
}

int main() {
while (scanf("%d", &n) && n != -1) {
printf("%dn", fibonacci(n));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: