当前位置:编程学习 > C/C++ >>

HDU 1588 Gauss Fibonacci 矩阵

[cpp] 
/**
  *stratege: 构造矩阵 A =  |1 1|
  *                        |1 0|
  *          矩阵快速幂,二分求和
  *status: johnsondu B Accepted 252 KB 15 ms C++ 3113 B 
  *
*/ 
 
 
#include <iostream> 
#include <cstdio> 
#include <cstring> 
#include <cmath> 
#include <algorithm> 
 
using namespace std; 
 
typedef __int64 LLD ; 
 
struct Matrix  

    LLD mat[2][2] ; 
}; 
Matrix tmp, unit, res ;  
LLD K, B, n, M ; 
Matrix a1, a2, a3 ; 
 
Matrix Multi (Matrix a, Matrix b)  //两矩阵相乘 

    Matrix c ; 
    for (int i = 0; i < 2;i ++) 
        for (int j = 0; j < 2; j ++) 
        { 
            c.mat[i][j] = 0 ; 
            for (int k = 0; k < 2; k ++) 
                c.mat[i][j] += (LLD)a.mat[i][k]*b.mat[k][j] ,c.mat[i][j] %= M ; //矩阵相乘时,需要防止溢出 
        } 
    return c ; 

 
Matrix power (LLD p)  //求出a1 = A^b 

    Matrix tp = unit ; 
    Matrix tr = tmp ; 
    while (p) 
    { 
        if (p&1) 
        { 
            tr = Multi (tr, tp) ; 
            p -- ; 
            continue ; 
        } 
        tp = Multi (tp, tp) ; 
        p >>= 1 ; 
    } 
    return tr ; 

 
 
Matrix power1 (LLD p) //求出a2 = A^k 

    Matrix tp = a2 ; 
    Matrix tr = tmp ; 
    while (p) 
    { 
        if (p&1) 
        { 
            tr = Multi (tr, tp) ; 
            p -- ; 
            continue ; 
        } 
        tp = Multi (tp, tp) ; 
        p >>= 1 ; 
    } 
    return tr ; 

 
Matrix add (Matrix a, Matrix b)  //矩阵相加 

    Matrix c ; 
     
    for (int i = 0; i < 2; i ++) 
        for (int j = 0; j < 2; j ++) 
            c.mat[i][j] = (a.mat[i][j] + b.mat[i][j]) % M ; 
    return c ; 

 
void init () 

    unit.mat[0][0] = 1 ;  //初始化矩阵 
    unit.mat[0][1] = 1 ; 
    unit.mat[1][0] = 1 ; 
    unit.mat[1][1] = 0 ; 
    tmp.mat[0][0] = 1 ;   //单位矩阵 
    tmp.mat[0][1] = 0 ; 
    tmp.mat[1][0] = 0 ; 
    tmp.mat[1][1] = 1 ; 
    a1 = power (B) ;      //由题意有ans = A^b + A^(k+b) + A^(2k+b) + ... + A^((n-1)k + b) 
    a2 = power (K) ;      //由此得出 a1 = A^b, a2 = A^k, 所以有ans = a1 * (E + a2^1 + a2^2 + ... + a2^(n-1)) ; 

 
Matrix MatrixSum (LLD p)  //求出E + a2^1 + a2^2 + ... + a2^(n-1) 

    if (p == 1)           //注意,此时p==1时,基为a2 = A^k 
        return a2 ;  
    Matrix tm, tr ; 
    tm = MatrixSum (p/2) ; 
    if (p & 1) 
    { 
        tr = power1 (p/2+1) ; 
        tm = add (tm, Multi (tm, tr)) ; 
        tm = add (tm, tr) ; 
    } 
    else { 
        tr = power1 (p/2) ; 
        tm = add (tm, Multi (tm, tr)) ; 
    } 
    return tm ; 
     

 
void output ()  //输出 

    if (n == 1) 
    { 
        printf ("%I64d\n", a1.mat[0][1]) ; 
        return ; 
    } 
         
    if (n == 0) 
    { 
        printf ("0\n") ; 
        return ; 
    } 
     
    Matrix ans = MatrixSum (n-1) ;  //因为是求出0~n-1, 此处先求出1~n-1 
    ans = add (ans, tmp) ;          //再求出与单位矩阵的和 
    ans = Multi (ans, a1) ;         //ans = a1 * (E + a2^1 + a2^2 + ... + a2^(n-1)) 
    printf ("%I64d\n", ans.mat[0][1] % M) ; //输出 

 
int main() 

    while (scanf ("%I64d%I64d%I64d%I64d", &K, &B, &n, &M) != EOF) 
    { 
        init () ; 
        output () ; 
    } 
    return 0; 

 


作者:zone_programming
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,