题解 P1357 花园
先考虑普通的DP,因为
从第二个样例来看,
可以知道前状态的最右几位要和后状态相同,不过最前面的一位被挤出去了,有没有摆C花没有关系,
另设
需要判一下第二个转移的前状态是否合法。
然后要处理环形的问题,可以简单的短环成链,然后对于给定初状态
依照这个思路写出40分代码:
#include <bits/stdc++.h>
int f[100000][1 << 5];
int n, m, K;
int t, ans;
int main() {
n = read(); m = read(); K = read();
t = (1 << m) - 1;
for (int statu = 0; statu <= t; ++statu) {
if (__builtin_popcount(statu) > K) continue;
memset(f, 0, sizeof(f));
f[0][statu] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= t; ++j) {
f[i][j] += f[i - 1][j >> 1];
if (__builtin_popcount((j >> 1) | (1 << (m - 1))) <= K)
f[i][j] += f[i - 1][(j >> 1) | (1 << (m - 1))];
}
}
ans += f[n][statu];
}
printf("%d\n", ans);
return 0;
}
\\ 不知道__builtin_popcount() 的可以自行百度,这是好东西
然后想着
构造出转移矩阵:
对于任意的
另外还有一点,对于之前每一个状态做一遍DP,现在我们有了矩阵,就没有必要对于
AC代码:
#include <bits/stdc++.h>
typedef long long lint;
inline lint read() {
lint x = 0, f = 0; char c = getchar();
for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = 1;
for (; c >= '0' && c <= '9'; c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
return f ? -x : x;
}
const int p = 1e9 + 7;
lint n;
int m, K;
int t, ans;
struct mat {
int row, col;
int a[32][32];
mat() {
memset(a, 0, sizeof(a));
}
void init() {
*this = mat();
row = col = t;
for (int i = 0; i < t; ++i)
a[i][i] = 1;
}
mat operator * (const mat &x) const {
mat ans = mat(); ans.row = row; ans.col = col;
for (int i = 0; i < row; ++i)
for (int j = 0; j < col; ++j)
for (int k = 0; k < col; ++k)
(ans.a[i][j] += (1ll * a[i][k] * x.a[k][j]) % p) %= p;
return ans;
}
mat operator ^ (lint n) {
mat ans = mat();
ans.init();
mat base = *this;
for (; n; n >>= 1, base = base * base)
if (n & 1) ans = ans * base;
return ans;
}
} ;
int main() {
n = read(); m = read(); K = read();
t = 1 << m;
mat b = mat(); b.row = b.col = t;
for (int i = 0, j; i < t; ++i) {
if (__builtin_popcount(i) > K) continue;
j = i >> 1;
// j -> i
b.a[j][i] = 1;
j = (i >> 1) | (1 << (m - 1));
if (__builtin_popcount(j) <= K)
b.a[j][i] = 1;
}
mat c = (b ^ n);
for (int i = 0; i < t; ++i) {
ans = (ans + c.a[i][i]) % p;
}
printf("%d\n", ans);
return 0;
}