Total Submission(s): 702 Accepted Submission(s): 412
The first ring can be taken off or taken on with one step.
If the first k rings are all off and the (k + 1)th ring is on, then the (k + 2)th ring can be taken off or taken on with one step. (0 ≤ k ≤ 7)
Now consider a game with N (N ≤ 1,000,000,000) rings on a bar, Dumbear wants to make all the rings off the bar with least steps. But Dumbear is very dumb, so he wants you to help him.
这道题 首先考虑,当前的灯能关的前提是前n-2个灯关上,当这个灯关上后,第n-1个灯还未关上,那么关上第n-1个灯又是要先打开第n-2个灯,依次类推,因为灯的状态从全开到全关,与从全关到全开是一致的,所以这道题的公式就是f[n] = f[n-2]+1 + f[n-2] + f[n-1] 合并后就是 f[n] = f[n-1] + 2*f[n-2] + 1
那么转换成矩阵后就很容易求解了
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 3
#define MOD 200907
using namespace std;
typedef long long LL;
int n;
struct Matrix
{
int a[MAX][MAX];
Matrix()
{
memset ( a , 0 , sizeof ( a ) );
}
};
Matrix multi ( Matrix m1 , Matrix m2 )
{
Matrix ret;
for ( int i = 0 ; i < MAX ; i++ )
for ( int j = 0 ; j < MAX ; j++ )
if ( m1.a[i][j] )
for ( int k = 0 ; k < MAX ; k++ )
ret.a[i][k] = ( ret.a[i][k] + ((LL)(m1.a[i][j])*(LL)(m2.a[j][k]))%MOD )%MOD;
return ret;
}
Matrix quick ( Matrix m , int n )
{
Matrix ret;
for ( int i = 0 ; i < MAX ; i++ )
ret.a[i][i] = 1;
while ( n )
{
if ( n&1 ) ret = multi ( ret , m );
m = multi ( m , m );
n >>= 1;
}
return ret;
}
int main ( )
{
while ( ~scanf ( "%d" , &n ) , n )
{
Matrix ans;
ans.a[0][0] = ans.a[0][2] = 1;
Matrix vary;
vary.a[0][0] = vary.a[0][1] = vary.a[2][2] = vary.a[2][0] = 1;
vary.a[1][0] = 2;
vary = quick ( vary , n-1 );
ans = multi ( ans , vary );
printf ( "%d\n" , ans.a[0][0] );
}
}