hdu 4291 A Short problem 矩阵快速幂

http://acm.hdu.edu.cn/showproblem.php?pid=4291

题意:...

思路:

首先暴力求出最外层模100000007的循环节MOD2,然后求出模MOD2的循环节MOD1.求出循环节后用类似与斐波那契数列举证优化的方法求解将时间复杂度由O(N)降到O(logN*2^3);

ps:注意这里我们虽然求(n - 1)次幂就能得到{fn,fn-1}了,但是对于当n等于0时就要特殊判断,单纯的一个求幂判断完毕也就罢了,但是当多次求幂时,里面套着也会出现0也需要判断。比较麻烦您容易忽略。所以我们可以求到a^n次方去a.mat[0][1] = a.mat[1][0]。 当计算n-1次幂时取a.mat[0][0]即可。

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   x < y ? x : y
#define Max(x, y)   x < y ? y : x
#define E(x)    (1 << (x))
#define iabs(x) (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()    freopen("data.in", "r", stdin)
#define Write()   freopen("data.out", "w", stdout);

const double eps = 1e-8;
typedef long long LL;
const int inf = ~0u>>2;

using namespace std;

int mod;
int l2 = 183120;
int l1 = 222222224;

struct Mat {
    LL mat[3][3];
    void init() {
        mat[0][0] = 3; mat[0][1] = 1;
        mat[1][0] = 1; mat[1][1] = 0;
    }
}a;

Mat operator * (Mat a, Mat b) {
    Mat c;
    CL(c.mat, 0);
    int i, j, k;
    REP(k, 2) {
        REP(i, 2) {
            if(a.mat[i][k] <= 0)    continue;
            REP(j, 2) {
                if(b.mat[k][j] <= 0)    continue;
                c.mat[i][j] = (c.mat[i][j] + (a.mat[i][k] * b.mat[k][j])%mod)%mod;
            }
        }
    }
    return c;
}

Mat operator ^ (Mat a, LL k) {
    Mat c;
    int i, j;
    REP(i, 2)    REP(j, 2)    c.mat[i][j] = (i == j);
    for(; k; k >>= 1) {
        if(k&1)    c = c*a;
        a = a*a;
    }
    return c;
}

LL solve(LL n, LL m) {
    a.init();
    mod = m;
    //if (n == 0) return 0;//这里是求n-1幂
    //a = a^(n - 1);
    a = a^n;
    return a.mat[1][0];
}

int main() {
    //freopen("din.txt", "r", stdin);
    LL n;
    while(cin >> n) {

        cout << solve(solve(solve(n, l2), l1), 1e9 + 7) << endl;
    }
    return 0;
}

 

posted @ 2012-09-19 19:17  E_star  阅读(242)  评论(0编辑  收藏  举报