题目:
题意:
对于一个 4 ∗ n 4*n 4∗n的矩阵,求用 1 ∗ 2 1*2 1∗2的小矩阵将其恰好填满的方案数
分析:
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[i−1]+a[i−2]∗5+a[i−3]−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;
}