Codility上的问题 (16) Omicron 2012

比较无聊的题,求斐波那契数的第N^M项。 f(0) = 0, f(1) = 1, f(n) = f(n - 1) + f(n - 2),结果对10000103取模。 N, M在[0..10^7]之间。要求复杂度:时间O(log(N * M)),空间O(1)。

分析: fib数取模有周期,并且对质数的周期一定是从最开头开始。也就在对P取模下,一定有f(T) == f(0)。关于周期的求法有原根之类的方法……但是本题直接暴力就行。算得

T = 20000208。后面就是矩阵乘方了。

代码:

// you can also use includes, for example:
// #include <algorithm>

#include <vector>
const int MOD = 10000103;
const int T = 20000208;

int mul(long long x,long long y,int M) {
    return x * y % M;
}

int add(int x,int y,int M) {
    return ((x += y) < M)?x:(x - M);
}

void mulmatrix(int a[2][2],int b[2][2],int c[2][2]) {
 int i,j,k;
    for (i = 0; i < 2; ++i) {
        for (j = 0; j < 2; ++j) {
            c[i][j] = 0;
            for (k = 0; k < 2; ++k) {
                c[i][j] = add(c[i][j], mul(a[i][k], b[k][j], MOD), MOD);
            }
        }
    }
}

void make(int a[2][2],int b[2][2]) {
int i,j;
    for (i = 0; i < 2; ++i) {
        for (j = 0; j < 2; ++j) {
            a[i][j] = b[i][j];
        }
    }
}


int solution(int N, int M) {
    // write your code here...
/*int T;
    vector<int> f;
    f.push_back(0);
    f.push_back(1);
    for (T = 2; ; ++T) {
        f.push_back(add(f[T - 1], f[T - 2], MOD));
        if ((f[T] == 1) && (f[T - 1] == 0)) {
            --T;
            break;
        }
    }
    return T;*/
    int p = 1, x = N;
    for (; M; M >>= 1) {
        if (M & 1) {
            p = mul(p,x,T);
        }
        x = mul(x,x,T);
    }
    if (p-- == 0) {
        return 0;
    }
    int a[2][2],b[2][2],c[2][2];
    a[0][0] = a[1][1] = b[0][1] = b[1][0] = b[1][1] = 1;
    a[0][1] = a[1][0] = b[0][0] = 0;
    for (; p; p >>= 1) {
        if (p & 1) {
            mulmatrix(a, b, c);
            make(a, c);
        }
        mulmatrix(b, b, c);
        make(b, c);
    }
    return a[1][1];
            
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值