HDU 6185 && 2017广西邀请赛:Covering(矩阵快速幂)



题意:

用1*2的骨牌铺满4*n的矩形总共有多种方法

经典题:可见骨牌铺方格的多种做法


因为宽只有4,考虑先求递推式,假设当前长度为x,有:

①长度为x-1的所有情况后面竖着放2个骨牌,f(x) += f(x-1)

②长度为x-2的所有情况后面横着放4个骨牌或者横着放2个,竖着放2个,而后者又有三种不同放法,f(x) += 4f(x-2)

③长度为x-3的所有情况后面横着放4个,竖着放2个,去掉和②重复的有2种情况,f(x) += 2f(x-3)

④长度为x-4的所有情况后面横着放6个,竖着放2个,去掉和②③重复的有3种情况,f(x) += 3f(x-4)

……(这里建议纸上画一画)

最后可以发现规律得到公式


将f(n)和f(n-1)相加有


这样就可以转成矩阵了


然后就可以愉快的快速幂了


#include<stdio.h>
#include<string.h>
#define mod 1000000007
#define LL long long
LL q[6] = {0,5,2,1,1};
typedef struct
{
	LL i, j;
	LL a[6][6];
	void init()
	{
		memset(a, 0, sizeof(a));
		a[1][4] = a[2][1] = a[2][2] = a[3][1] = a[4][3] = 1;
		a[1][2] = 5;
	}
	void unit()
	{
		memset(a, 0, sizeof(a));
		for(i=1;i<=4;i++)
			a[i][i] = 1;
	}
}Matrix;
Matrix Jz;
Matrix Powto(Matrix p, LL k);
Matrix Jjcf(Matrix p1, Matrix p2);
int main(void)
{
	LL i, n, ans;
	while(scanf("%lld", &n)!=EOF)
	{
		if(n==1)
			printf("1\n");
		else if(n==2)
			printf("5\n");
		else
		{
			Jz.init();
			Jz = Powto(Jz, n-2);
			ans = 0;
			for(i=1;i<=4;i++)
				ans = (ans+q[i]*Jz.a[1][i])%mod;
			printf("%lld\n", ans);
		}
	}
	return 0;
}

Matrix Powto(Matrix p, LL k)
{
	Matrix E;
	E.unit();
	while(k)
	{
		if(k%2)
			E = Jjcf(E, p);
		p = Jjcf(p, p);
		k /= 2;
	}
	return E;
}

Matrix Jjcf(Matrix p1, Matrix p2)
{
	Matrix pe;
	LL i, j, k;
	memset(pe.a, 0, sizeof(pe.a));
	for(i=1;i<=4;i++)
	{
		for(j=1;j<=4;j++)
		{
			for(k=1;k<=4;k++)
				pe.a[i][j] = (pe.a[i][j]+p1.a[i][k]*p2.a[k][j])%mod;
		}
	}
	return pe;
}

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值