另设传送门
Description
Analysis
骨牌填矩阵的模型,
显然N与N-1间是有关联的!
递推难以保证合法性,
考虑状压DP
设f[i][s]上一列状态为S,本列是i+1列
剩下的自己YY吧。
这样是O(n)的
不要忘了矩阵快速幂优化加速。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn = 16;
long long n,m;
long long c[maxn][maxn],f[maxn][maxn],A[maxn][maxn],B[maxn][maxn];//临时数组,DP数组,临时数组,友矩阵
bool bz[16]={1,0,0,1,0,0,0,0,0,1,0,0,1,0,0,1};//0 3 6 12 15 即可转移至f[i][15]的s
void mul_a() //矩阵乘法
{
memset(c,0,sizeof(c));
for(int i = 0;i <= 15;i ++)
for(int j = 0;j <= 15;j ++)
for(int k = 0;k <= 15;k ++)
c[i][j] = (c[i][j] + (f[i][k] * A[k][j]) % m) % m;
memcpy(f,c,sizeof(c));
}
void sqr_a() //矩阵乘法
{
memset(c,0,sizeof(c));
for(int i = 0;i <= 15;i ++)
for(int j = 0;j <= 15;j ++)
for(int k = 0;k <= 15;k ++)
c[i][j] = (c[i][j] + (A[i][k] * A[k][j]) % m) % m;
memcpy(A,c,sizeof(c));
}
void qsm_f(long long n) //矩阵快速幂
{
for(;n;n>>=1)
{
if (n & 1 == 1)
mul_a(); //f = f * A
sqr_a();//A = A * A
}
}
int main()
{
for(int i = 0;i <= 15;i ++)
for(int j = 0;j <= 15;j ++)
if((i & j) == 0 && bz[i | j])
B[i][j]=1;
//求友矩阵
scanf("%lld%lld", &n, &m);
while (n + m > 0)
{
memcpy(A,B,sizeof(B));
memset(f,0,sizeof(f));
//初始化
f[0][0] = 1;
qsm_f(n);
printf("%lld\n", f[0][0]);
scanf("%lld%lld", &n, &m);
}
}