Chinese Rings (HDU 2842 矩阵快速幂带常数和系数)

Chinese Rings

Time 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.
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.

 

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;
}


 

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/88632474
今日推荐