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];

            

}


 

 

你可能感兴趣的:(cron)