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

 

 

posted @ 2012-11-04 13:48  moonbay  阅读(173)  评论(0编辑  收藏  举报