Chinese RingsTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1598 Accepted Submission(s): 928 Problem Description Dumbear likes to play the Chinese Rings (Baguenaudier). It’s a game played with nine rings on a bar. The rules of this game are very simple: At first, the nine rings are all on the bar. Input Each line of the input file contains a number N indicates the number of the rings on the bar. The last line of the input file contains a number "0". Output For each line, output an integer S indicates the least steps. For the integers may be very large, output S mod 200907. Sample Input 1 4 0 Sample Output 1 10 Source 2009 Multi-University Training Contest 3 - Host by WHU Recommend gaojie | We have carefully selected several similar problems for you: 2841 2844 2843 2840 2839 |
上一篇文章中有讲过如何处理常数和系数。然后这个题的递推式怎么来的呢?
记取完n个环需要的步数是F(N) 类似前面取三个环的思路
首先取第n个环,条件是n-1个环在上面&&前n-2个环不在上面(step=F(N-2))。然后取下第n个环(step=F(N-2)+1)
现在取下第n-1个环,条件是前n-2个环在上面,那么放上前n-2个(step=F(N-2)+1+F(N-2))现在变成了n-1个环,那么直接
取前n-1个环又要消耗F[N-1]个步骤。step=F(N-2)+1+F(N-2)+F(N-1)。
取下前n-1个环自然而然的就把前n-2个环全取下了。
1.f(n)=f(n-1)+2*f(n-2)+1即为递推式。另:初始化f(1)=1,f(2)=2
2.矩阵快速幂中,遇到含有常数的式子,可以把A矩阵扩展为3*3的矩阵。
即最终得到下式:
| f(n) | | 1 2 1 | | f(n-1) |
| f(n-1) | = | 1 0 0 | * | f(n-2) |
| 1 | | 0 0 1 | | 1 |
以上的方法就可以解决带有系数或者带有常数的情况。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=3,mod=200907;
struct Matrix
{
ll mat[MAXN][MAXN];
Matrix() {}
Matrix operator*(Matrix const &b)const
{
Matrix res;
memset(res.mat, 0, sizeof(res.mat));
for (int i = 0 ;i < MAXN; i++)
for (int j = 0; j < MAXN; j++)
for (int k = 0; k < MAXN; k++)
res.mat[i][j] = (res.mat[i][j]+this->mat[i][k] * b.mat[k][j])%mod;
return res;
}
};
Matrix pow_mod(Matrix base, int n)
{
Matrix res;
memset(res.mat, 0, sizeof(res.mat));
for (int i = 0; i < MAXN; i++)
res.mat[i][i] = 1;
while (n > 0)
{
if (n & 1) res = res*base;
base = base*base;
n >>= 1;
}
return res;
}
Matrix base,fi;
int main()
{
base.mat[0][0] = 1;
base.mat[0][1] = 2;
base.mat[0][2] = 1;
base.mat[1][0] = 1;
base.mat[2][2] = 1;
fi.mat[0][0]=2;
fi.mat[1][0]=1;
fi.mat[2][0]=1;
int n;
while (~scanf("%d", &n)&&n)
{
if(n<=2)
{
printf("%d\n",n);
continue;
}
Matrix ans = pow_mod(base, n-2);
ans=ans*fi;
printf("%lld\n", ans.mat[0][0]);
}
return 0;
}