题意:求出最少步骤解出九连环。
取出第k个的条件是,k-2个已被取出,k-1个仍在支架上。
思路:想必九连环都玩过吧,事实上最少步骤就是从最后一个环開始。向前一直取出来即可了。
所以如果取出前n个环所须要的步骤为f(n),那么在此之前f(n - 2)要被取出,再加上1。即第n个环被取出,所以仅仅剩下第n-1环没被取出,那么我们将前n-2环再套上去(套上去和取下来的步骤是一样。都为f(n - 2)),所以取出n-1环的步骤为f(n - 1),因此能够得到一个递推公式:f(n) = f(n - 2) + 1 + f(n - 2) + f(n - 1) = f(n - 1) + 2f(n - 2) + 1;
由于n偏大。所以使用矩阵高速幂进行运算就能够了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
//typedef long long ll;
typedef __int64 ll;
const int MOD = 200907;
struct mat {
ll s[3][3];
mat () {
memset(s, 0, sizeof(s));
}
mat operator * (const mat& c) {
mat ans;
memset(ans.s, 0, sizeof(ans.s));
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
for (int k = 0; k < 3; k++)
ans.s[i][j] = (ans.s[i][j] + s[i][k] * c.s[k][j]) % MOD;
return ans;
}
}tmp, c;
ll n;
void init() {
tmp.s[0][0] = tmp.s[0][2] = tmp.s[1][0] = tmp.s[2][2] = c.s[1][0] = c.s[2][0] = 1;
tmp.s[0][1] = c.s[0][0] = 2;
}
mat pow_mod(ll k) {
if (k == 1)
return tmp;
mat a = pow_mod(k / 2);
mat ans = a * a;
if (k % 2)
ans = ans * tmp;
return ans;
}
int main() {
init();
while (scanf("%I64d", &n) && n) {
if (n == 1 || n == 2) {
printf("%I64d\n", n);
continue;
}
mat ans = pow_mod(n - 2);
ans = ans * c;
printf("%I64d\n", ans.s[0][0]);
}
return 0;
}