hdu 4291矩阵快速幂

这题是去年成都网络赛的题,当时没做出来,杯具呀。

其实最关键的就是要懂得取余一定会循环的,如果能够找出循环节,就是一个巨大的突破。然后就是g(n)的求法,很显然硬求是不可能的,我们去年做这题的时候试图去找g(n)的通项公式,都找得差不多了,但实际上那毫无意义。因为我们是要找循环节,所以应该一层层地找。先看g(n) % 1000000007到哪里会循环。可以用矩阵的方法求g(n),暴力打出来,发现循环节是222222224。再来看g(g(n)) % 1000000007到哪里会循环。因为g(g(n)) % 1000000007对g(n)每隔222222224结果就会循环一次,所以g(g(n)) % 1000000007 = g(g(n) % 222222224) % 1000000007。所以g(n) % 222222224的循环节也就是g(g(n)) % 1000000007的循环节。暴力求出来是183120。最后再看g(g(g(n))) % 1000000007的循环节。同理g(n) % 183120的循环节就是g(g(g(n))) % 1000000007的循环节。暴力求出来是240。也就是说,最后的结果,n每隔240就会循环。所以最后的结果就是g(g(g(n % 240) % 183120) % 222222224) % 1000000007。用矩阵快速幂就可以过了。

我的暴力求循环节的代码如下:

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <cmath>

#include <ctime>

#include <iostream>

#include <algorithm>

#include <queue>

#include <set>

#include <map>

#include <stack>

#include <string>

#include <vector>

#include <deque>

#include <list>

#include <functional>

#include <numeric>

#include <cctype>

using namespace std;

const int MAX_ORDER = 2;

const int MOD = 1000000007;

typedef long long typec;

typedef struct MyMatrix {

    int row, col;

    typec num[MAX_ORDER][MAX_ORDER];

    MyMatrix(int rr, int cc) {

        row = rr;

        col = cc;

    }

    inline void init() {

        memset(num, 0, sizeof(num));

    }

} MyMatrix;

//矩阵乘法。注意:ma.col与mb.row一定要相等,否则会出问题

MyMatrix operator*(MyMatrix ma, MyMatrix mb) {

    int row = ma.row;

    int col = mb.col;

    int K = ma.col;

    MyMatrix numc(row, col);

    numc.init();

    int i, j, k;

    for (i = 0; i < row; i++) {

        for (j = 0; j < col; j++) {

            for (k = 0; k < K; k++) {

                numc.num[i][j] += ma.num[i][k] * mb.num[k][j];

                numc.num[i][j] %= MOD;

            }

        }

    }

    return numc;

}

//矩阵快速幂。注意:ma.col与ma.row一定要相等,否则会出问题

MyMatrix mpow(MyMatrix ma, int x) {

    int ord = ma.row;

    MyMatrix numc(ord, ord);

    numc.init();

    for (int i = 0; i < ord; i++) {

        numc.num[i][i] = 1;

    }

    for (; x; x >>= 1) {

        if (x & 1) {

            numc = numc * ma;

        }

        ma = ma * ma;

    }

    return numc;

}



int main() {

#ifndef ONLINE_JUDGE

    freopen("data.in", "r", stdin);

#endif

    MyMatrix ori(1, 2);

    ori.num[0][0] = 0;

    ori.num[0][1] = 1;

    MyMatrix tran(2, 2);

    tran.num[0][0] = 0;

    tran.num[0][1] = 1;

    tran.num[1][0] = 1;

    tran.num[1][1] = 3;

    for(int t = 1; ; t++) {

        ori = ori * tran;

        if(ori.num[0][0] == 0 && ori.num[0][1] == 1) {

            printf("%d\n", t);

            break;

        }

    }

    return 0;

}

最后通过的代码如下:

/*

 * hdu4291/win.cpp

 * Created on: 2012-11-4

 * Author    : ben

 */

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <cmath>

#include <ctime>

#include <iostream>

#include <algorithm>

#include <queue>

#include <set>

#include <map>

#include <stack>

#include <string>

#include <vector>

#include <deque>

#include <list>

#include <functional>

#include <numeric>

#include <cctype>

using namespace std;

const int MAX_ORDER = 2;

int MOD;

typedef long long typec;

typedef struct MyMatrix {

    int row, col;

    typec num[MAX_ORDER][MAX_ORDER];

    MyMatrix(int rr, int cc) {

        row = rr;

        col = cc;

    }

    inline void init() {

        memset(num, 0, sizeof(num));

    }

} MyMatrix;

//矩阵乘法。注意:ma.col与mb.row一定要相等,否则会出问题

MyMatrix operator*(MyMatrix ma, MyMatrix mb) {

    int row = ma.row;

    int col = mb.col;

    int K = ma.col;

    MyMatrix numc(row, col);

    numc.init();

    int i, j, k;

    for (i = 0; i < row; i++) {

        for (j = 0; j < col; j++) {

            for (k = 0; k < K; k++) {

                numc.num[i][j] += ma.num[i][k] * mb.num[k][j];

                numc.num[i][j] %= MOD;

            }

        }

    }

    return numc;

}

//矩阵快速幂。注意:ma.col与ma.row一定要相等,否则会出问题

MyMatrix mpow(MyMatrix ma, int x) {

    int ord = ma.row;

    MyMatrix numc(ord, ord);

    numc.init();

    for (int i = 0; i < ord; i++) {

        numc.num[i][i] = 1;

    }

    for (; x; x >>= 1) {

        if (x & 1) {

            numc = numc * ma;

        }

        ma = ma * ma;

    }

    return numc;

}



inline MyMatrix getori() {

    MyMatrix ori(1, 2);

    ori.num[0][0] = 0;

    ori.num[0][1] = 1;

    return ori;

}



inline MyMatrix gettran() {

    MyMatrix tran(2, 2);

    tran.num[0][0] = 0;

    tran.num[0][1] = 1;

    tran.num[1][0] = 1;

    tran.num[1][1] = 3;

    return tran;

}



int main() {

#ifndef ONLINE_JUDGE

    freopen("data.in", "r", stdin);

#endif

    long long temp;

    while(scanf("%I64d", &temp) == 1) {

        int n = (int)(temp % 240);

        MOD = 183120;

        n = (getori() * mpow(gettran(), n)).num[0][0];

        MOD = 222222224;

        n = (getori() * mpow(gettran(), n)).num[0][0];

        MOD = 1000000007;

        n = (getori() * mpow(gettran(), n)).num[0][0];

        printf("%d\n", n);

    }

    return 0;

}

 

 

你可能感兴趣的:(HDU)