2013寒假练习 1019 The Little Architect II

13 篇文章 0 订阅
5 篇文章 0 订阅

地址:http://acm.bit.edu.cn/mod/programming/view.php?id=670

用1*1*2的积木装满2*2*n的矩阵,一共有几种方法。答案mod p输出(1 <= n <= 1,000,000,000, 1 < p <= 1,000,000)

这题想了我好几天,终于想明白每一层只有三种可能:不放向下的(情况0),放两个相邻的向下的(情况1),放四个向下的(情况2)。则由状态压缩DP的思想可以得到递推公式:

dp[i][0]=dp[i-1][0]*2+dp[i-1][1]+dp[i-1][2];

dp[i][1]=dp[i-1][0]*4+dp[i-1][1];

dp[i][2]=dp[i-1][0];

初始条件

dp[0][0]=1,dp[0][1]=dp[0][2]=0;

这是由类似1022的思想想出来的。。然而n数据规模巨大,o(n)的递推上去都不能被接受。。一开始想到的是因为mod p,是否可以跑出循环节,结果仍旧超时,说明循环节都有可能很长。。

正解应该是矩阵快速幂优化递推关系!

构造矩阵[2 4 1]  答案即变为该矩阵的n次方的(0,0)位置的值!然后用矩阵快速幂瞬解。

                [1 1 0]

                [1 0 0]

好题。。

补充:刘果大神推出的另一个递推公式:f(n)=3f(n-1)+3f(n-2)-f(n-3)

#include<iostream>
using namespace std;
typedef struct MATRIX
{
	__int64 a[3][3];
}matrix;
int n,p,i,j;
matrix operator * (matrix x,matrix y)
{
	matrix ans;
	for(i=0;i<=2;i++)
	{
		for(j=0;j<=2;j++)
		{
			ans.a[i][j]=(x.a[i][0]*y.a[0][j]%p+x.a[i][1]*y.a[1][j]%p+x.a[i][2]*y.a[2][j]%p)%p;
		}
	}
	return ans;
}
int main()
{
	while(~scanf("%d%d",&n,&p))
	{
		matrix I={2,4,1,1,1,0,1,0,0};
		matrix t={1,0,0,0,1,0,1,0,0};
		while(n>1)
		{	
			if(n%2) t=t*I;
			n/=2,I=I*I;	
		}
		t=t*I;
		printf("%d\n",t.a[0][0]);
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值