Problem 1683 纪念SlingShot .
思路
构造矩阵T S(n) = Tn-2 [0][0] × S(2) + Tn-2 [0][1] × f(2) + Tn-2 [0][2] × f(1) + Tn-2 [0][3] × f(0) S(2) = 9,f(0) = 1,f(1) = 3,f(3) = 5 超时了,查题解看到把矩阵每次乘法的结果储存起来再调用可以省时间,即存储T,T2 ,T4 ,T8 ……一直到T32 (int型数据最大232 ,long long 264 ,快速幂中a作为乘数的最大值即为232 ,矩阵同理)
笔记
快速幂+矩阵快速幂详解戳这里 矩阵快速幂总结
typedef long long LL;
const int N = 4 ;
struct Matrix{
int v[ N] [ N] ;
void init0 ( ) {
memset ( v, 0 , sizeof ( v) ) ;
}
void init1 ( ) {
memset ( v, 0 , sizeof ( v) ) ;
for ( int i= 0 ; i< N; i++ )
v[ i] [ i] = 1 ;
}
} begin, list[ 35 ] ;
Matrix multi ( Matrix a, Matrix b) {
Matrix tmp;
tmp. init0 ( ) ;
for ( int i= 0 ; i< N; i++ ) {
for ( int j= 0 ; j< N; j++ )
for ( int k= 0 ; k< N; k++ )
tmp. v[ i] [ j] + = a. v[ i] [ k] * b. v[ k] [ j] ;
}
return tmp;
}
Matrix pow ( int n, Matrix list[ ] ) {
int add = 1 ;
Matrix res;
res. init1 ( ) ;
while ( n && add<= 32 ) { #数组越界保护
if ( n& 1 )
res = multi ( res, list[ add] ) ;
add++ ;
n >>= 1 ;
}
return res;
}
代码
#include <stdio.h>
#include <string.h>
using namespace std;
typedef long long LL;
const int N = 4 , mymod = 2009 ;
struct Matrix{
int v[ N] [ N] ;
void init0 ( ) {
memset ( v, 0 , sizeof ( v) ) ;
}
void init1 ( ) {
memset ( v, 0 , sizeof ( v) ) ;
for ( int i= 0 ; i< N; i++ )
v[ i] [ i] = 1 ;
}
void init_begin ( ) {
memset ( v, 0 , sizeof ( v) ) ;
v[ 0 ] [ 0 ] = 1 ; v[ 0 ] [ 1 ] = 3 ; v[ 0 ] [ 2 ] = 2 ; v[ 0 ] [ 3 ] = 7 ;
v[ 1 ] [ 0 ] = 0 ; v[ 1 ] [ 1 ] = 3 ; v[ 1 ] [ 2 ] = 2 ; v[ 1 ] [ 3 ] = 7 ;
v[ 2 ] [ 0 ] = 0 ; v[ 2 ] [ 1 ] = 1 ; v[ 2 ] [ 2 ] = 0 ; v[ 2 ] [ 3 ] = 0 ;
v[ 3 ] [ 0 ] = 0 ; v[ 3 ] [ 1 ] = 0 ; v[ 3 ] [ 2 ] = 1 ; v[ 3 ] [ 3 ] = 0 ;
}
} ;
Matrix begin, list[ 35 ] ;
Matrix multi ( Matrix a, Matrix b) {
Matrix tmp;
tmp. init0 ( ) ;
for ( int i= 0 ; i< N; i++ ) {
for ( int j= 0 ; j< N; j++ )
for ( int k= 0 ; k< N; k++ )
tmp. v[ i] [ j] = ( tmp. v[ i] [ j] + ( a. v[ i] [ k] * b. v[ k] [ j] % mymod) ) % mymod;
}
return tmp;
}
Matrix pow ( int n, Matrix list[ ] ) {
int add = 1 ;
Matrix res;
res. init1 ( ) ;
while ( n && add<= 32 ) {
if ( n& 1 )
res = multi ( res, list[ add] ) ;
add++ ;
n >>= 1 ;
}
return res;
}
int main ( ) {
int m, n;
LL ans;
scanf ( "%d" , & m) ;
begin. init_begin ( ) ;
for ( int i= 1 ; i<= 32 ; i++ ) {
list[ i] = begin;
begin = multi ( begin, begin) ;
}
for ( int i= 1 ; i<= m; i++ ) {
scanf ( "%d" , & n) ;
if ( n== 0 )
printf ( "Case %d: 1\n" , i) ;
else if ( n== 1 )
printf ( "Case %d: 4\n" , i) ;
else if ( n== 2 )
printf ( "Case %d: 9\n" , i) ;
else {
begin = pow ( n- 2 , list) ;
ans = ( begin. v[ 0 ] [ 0 ] * 9 + begin. v[ 0 ] [ 1 ] * 5 + begin. v[ 0 ] [ 2 ] * 3 + begin. v[ 0 ] [ 3 ] * 1 ) % mymod;
printf ( "Case %d: %lld\n" , i, ans) ;
}
}
return 0 ;
}