HDU 1588 Gauss Fibonacci 矩阵

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


你可能感兴趣的:(C++,c,struct,Matrix,output)