JZOJ 4787. 【NOIP2016提高A组模拟9.17】数格子


题目:

传送门


题意:

对于一个 4 ∗ n 4*n 4n的矩阵,求用 1 ∗ 2 1*2 12的小矩阵将其恰好填满的方案数


分析:

O E I S 大 法 好 OEIS大法好 OEIS
这个不解释,谁用谁说好
a [ i ] = a [ i − 1 ] + a [ i − 2 ] ∗ 5 + a [ i − 3 ] − a [ 4 ] a[i]=a[i-1]+a[i-2]*5+a[i-3]-a[4] a[i]=a[i1]+a[i2]5+a[i3]a[4]
然后对于这个式子用矩阵乘法进行优化


代码:

#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define LL long long 
#define LZXANDME 1314 
inline LL read() {
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}
using namespace std;
LL n,LZX;
const LL s[5][5]=
{
	{0,0,0,0,0},
	{0,1,5,1,-1},
	{0,1,0,0,0},
	{0,0,1,0,0},
	{0,0,0,1,0}
};
LL f[5],x[5][5];
void mul()
{
	LL e[5];memset(e,0,sizeof(e));
	for(LL i=1;i<=4;i++)
	  for(LL j=1;j<=4;j++)
	    (e[i]+=f[j]*x[i][j])%=LZX;
	memcpy(f,e,sizeof(e));
	return;
}
void mulself()
{
	LL e[5][5];memset(e,0,sizeof(e));
	for(LL i=1;i<=4;i++)
	  for(LL j=1;j<=4;j++)
	    for(LL k=1;k<=4;k++)
	      (e[i][j]+=x[i][k]*x[k][j])%=LZX;
	memcpy(x,e,sizeof(e));
	return;
}
int main()
{	
	while(1)
	{
		n=read();LZX=read();
		if (n==1) {printf("1\n"); continue;}
		if (n==2) {printf("5\n"); continue;}
		if (n==3) {printf("11\n"); continue;}
		if (n==4) {printf("36\n"); continue;}
		if(!n&&!LZX) break;
		f[4]=1%LZX;f[3]=5%LZX;f[2]=11%LZX;f[1]=36%LZX;
		memcpy(x,s,sizeof(s));
		n-=4;
		while(n)
		{
			if(n&1) mul();
			mulself();
			n>>=1;
		}
		printf("%lld\n",(f[1]%LZX+LZX)%LZX);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值