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

 

转载于:https://www.cnblogs.com/E-star/archive/2012/09/19/2694187.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值