题目分析:矩阵快速幂妥妥的。
首先我们设斐波那契第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 ;
}