您的位置:首页 > 其它

HDU 2842 Chinese Rings(矩阵快速幂)

2014-04-20 18:40 239 查看
转载请注明出处:http://blog.csdn.net/u012860063

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2842

[题意]

* 有n个灯,初始时是全亮的,第一个灯可以按(按下之后改变状态)

* 然后如果前k个灯全灭且第k+1个灯亮,则第k+2个灯可以按

* 问至少要多少步灭掉所有灯?

* [解题方法](对于n个灯,所求为f


* 1. 要想灭掉最后一个灯,得先灭掉前n-2个灯(第n-1个灯留亮)(f[n-2]+1)

* {注:灭掉最后一个灯需要1步}

* 2. 要想灭掉第n-1个灯,得先让第n-2个灯变回亮,要第n-2个灯变回亮,得先让第n-3个灯变回亮...

* 即要把前n-2个灯都变回亮(f[n-2])

* 3. 把前n-2个灯变回亮后,就剩下前n-1个灯是亮的,即剩下的任务就是把n-1个灯灭掉(f[n-1])

* 综上所述:f
= 2*f[n-2] + f[n-1] + 1

* 所以得矩阵:

* |1 2 1| |f[n-1]| |f
|

* |1 0 0| * |f[n-2]| = |f[n-1]|

* |0 0 1| |1 | |1 |

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Matrix
{
	__int64  m[5][5];
}I,A,T;
__int64 a,b,n,mod;
Matrix matrixmul(Matrix a,Matrix b)
{
	__int64 i,j,k;
	Matrix c;
	for (i=1;i<=3;i++)
		for(j=1;j<=3;j++)
		{
			c.m[i][j]=0;
			for(k=1;k<=3;k++)
			{
				c.m[i][j]+=(a.m[i][k]*b.m[k][j]);
				c.m[i][j]%=200907;
			}
		}
		return c;
}
Matrix quickpagow(__int64 n)
{
	Matrix m=A,b=I;
	while (n>=1)
	{
		if(n&1)
			b=matrixmul(b,m);
		n=n>>1;
		m=matrixmul(m,m);
	}
	return b;
}

int main()
{
	__int64 ans,i;
	while(scanf("%I64d",&n)!=EOF)
	{
		if(n == 0)
			break;
		memset(I.m,0,sizeof(I.m));
		memset(A.m,0,sizeof(A.m));
		for(i=1;i<=3;i++)
		{
			I.m[i][i]=1;
		}
		A.m[1][1]=1,A.m[1][2]=2,A.m[1][3]=1;
		A.m[2][1]=A.m[3][3]=1;
		T=quickpagow(n);
		printf("%I64d\n",T.m[1][3]%200907);
	}
	
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: