现在的位置: 首页 > 综合 > 正文

【HDU】1588 Gauss Fibonacci 矩阵快速幂

2017年10月15日 ⁄ 综合 ⁄ 共 2160字 ⁄ 字号 评论关闭

传送门:【HDU】1588 Gauss Fibonacci

题目分析:矩阵快速幂妥妥的。


首先我们设斐波那契第N项为f( n ),则:

           | 1   1 |

 令A = |         |,则f( n ) 等于( A^n )的右上角那项。
           | 1   0 |

然后f( g( i ) ) = f ( k * i + b ) = ( A ^ ( k * i ) ) * ( A ^ b )

易得res = sum{f( g( i ) ),0 <= i < n } = ( A ^ b ) * ( E(单位矩阵) + A^k + A^( 2k ) + A^( 3k ) + …… + A^( (n - 1)k )。

                           | E  0 |

令C = A^k , B = |         |,则B ^ ( n - 1 )的左下角即D = A^k + A^( 2k ) + A^( 3k ) + …… + A^( ( n - 1 )k )

                           | C C |

则res = ( A ^ b ) * ( D + E )。

矩阵res的右上角即答案。


代码如下:


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

typedef long long LL ;

#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define rep( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define F( i ) ( ( ( i ) - 1 ) % n + 1 )

const int MAXN = 4 ;
int mod ;

struct Matrix {
	LL mat[MAXN][MAXN] ;
	int n ;
	Matrix () {}
	Matrix ( int n ) : n ( n ) {}
	
	void clear () {
		clr ( mat , 0 ) ;
	}
	
	void init () {
		rep ( i , 0 , n ) rep ( j , 0 , n ) mat[i][j] = i == j ;
	}
	
	Matrix operator * ( const Matrix& a ) const {
		Matrix c ( n ) ;
		c.clear () ;
		rep ( i , 0 , n ) rep ( j , 0 , n ) rep ( k , 0 , n ) {
			c.mat[i][j] = ( c.mat[i][j] + mat[i][k] * a.mat[k][j] ) % mod ;
		}
		return c ;
	}
	
	Matrix operator + ( const Matrix& a ) const {
		Matrix c ( n ) ;
		rep ( i , 0 , n ) rep ( j , 0 , n ) {
			c.mat[i][j] = mat[i][j] + a.mat[i][j] ;
			if ( c.mat[i][j] >= mod ) c.mat[i][j] -= mod ;
		}
		return c ;
	}
	
	Matrix operator *= ( const Matrix& a ) const {
		return ( *this ) * a ;
	}
	
	Matrix operator += ( const Matrix& a ) const {
		return ( *this ) + a ;
	}
} ;

int k , b , n ;

Matrix pow ( Matrix A , int b ) {
	Matrix res ( A.n ) ;
	res.init () ;
	Matrix tmp = A ;
	while ( b ) {
		if ( b & 1 ) res = res * tmp ;
		tmp = tmp * tmp ;
		b >>= 1 ;
	}
	return res ;
}

void solve () {
	Matrix A ( 2 ) ;//Fibonacci
	Matrix B ( 4 ) ;//A^k矩阵的构造矩阵
	Matrix C ( 2 ) ;//求A^k
	Matrix D ( 2 ) ;//B矩阵的k次方和
	Matrix E ( 2 ) ;//单位矩阵
	E.init () ;
	A.mat[0][0] = 1 ; A.mat[0][1] = 1 ;
	A.mat[1][0] = 1 ; A.mat[1][1] = 0 ;
	C = pow ( A , k ) ;
	B.mat[0][0] = 1 ;           B.mat[0][1] = 0 ;           B.mat[0][2] = 0 ;           B.mat[0][3] = 0 ;
	B.mat[1][0] = 0 ;           B.mat[1][1] = 1 ;           B.mat[1][2] = 0 ;           B.mat[1][3] = 0 ;
	B.mat[2][0] = C.mat[0][0] ; B.mat[2][1] = C.mat[0][1] ; B.mat[2][2] = C.mat[0][0] ; B.mat[2][3] = C.mat[0][1] ;
	B.mat[3][0] = C.mat[1][0] ; B.mat[3][1] = C.mat[1][1] ; B.mat[3][2] = C.mat[1][0] ; B.mat[3][3] = C.mat[1][1] ;
	B = pow ( B , n - 1 ) ;
	D.mat[0][0] = B.mat[2][0] ; D.mat[0][1] = B.mat[2][1] ;
	D.mat[1][0] = B.mat[3][0] ; D.mat[1][1] = B.mat[3][1] ;
	Matrix res = pow ( A , b ) * ( D + E ) ;
	printf ( "%I64d\n" , res.mat[0][1] ) ;
}

int main () {
	while ( ~scanf ( "%d%d%d%d" , &k , &b , &n , &mod ) ) solve () ;
	return 0 ;
}

抱歉!评论已关闭.