【拼图——拼图类压缩dp,矩阵乘法,快速幂,DFS】
题目
分析
难点在于看出相邻列之间状态的转移是按照固定的状态转移矩阵进行的,并依据此采用矩阵乘法+快速幂来优化
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int mod = 1e9 + 7;
const int M = 1 << 7;
ll m;
int n;
int w[M][M];
int ans[M][M];
void dfs(int r, int j, int ne)
{
if (r >= n)
{
w[j][ne] += 1;
return;
}
if (j & (1 << r))
dfs(r + 1, j, ne);
else
{
if (r - 1 >= 0 && (ne & (1 << r - 1)) == 0 && (ne & (1 << r)) == 0)
dfs(r + 1, j, ne | (1 << r - 1) | (1 << r));
if (r + 1 < n && (ne & (1 << r)) == 0 && (ne & (1 << r + 1)) == 0)
dfs(r + 1, j, ne | (1 << r) | (1 << r + 1));
if (r + 1 < n && (j & (1 << r + 1)) == 0 && (ne & (1 << r)) == 0)
dfs(r + 2, j, ne | (1 << r));
if (r + 1 < n && (j & (1 << r + 1)) == 0 && (ne & (1 << r + 1)) == 0)
dfs(r + 2, j, ne | (1 << r + 1));
}
}
void mul(int a[][M], int b[][M], int c[][M])
{
static int t[M][M];
memset(t, 0, sizeof t);
for (int i = 0; i < 1 << n; i++)
for (int j = 0; j < 1 << n; j++)
for (int k = 0; k < 1 << n; k++)
t[i][j] = (t[i][j] + 1ll * a[i][k] * b[k][j] % mod) % mod;
memcpy(c, t, sizeof t);
}
void qmi(ll expo, int a[][M], int b[][M])
{
while (expo)
{
if (expo & 1)
mul(ans, w, ans);
mul(w, w, w);
expo >>= 1;
}
}
int main()
{
scanf("%lld%d", &m, &n);
for (int j = 0; j < 1 << n; j++)
dfs(0, j, 0);
ans[0][0] = 1;
qmi(m, ans, w);
printf("%d", ans[0][0]);
}