3070 Fibonacci(O(log n)求解 )

来源:互联网 发布:网络奇兵2剧情 编辑:程序博客网 时间:2024/06/03 10:34

Fibonacci序列可由此公式求出:

[转载]poj <wbr><wbr>3070 <wbr><wbr>Fibonacci(O(log <wbr><wbr>n)求解)

设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 10000int 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));    }}


原创粉丝点击