P5005题解
谨以此篇题解纪念我首个完全独立思考 AC 的紫题。
首先,本题一眼看上去就是个炮兵阵地加强版,然后数据范围
显然,我们需要设计一个
最主要的是
这里是关键部分的代码,其中后两行是判断若该点放置的话会不会影响前面的局面,即能够攻击到上面的马:
for (int k=0; k<=((1<<m)-1); k++) {
for (int l=0; l<=((1<<m)-1); l++) {
for (int j=0; j<m; j++) {
if ((k>>1)&(1<<j))if (!((l>>1)&(1<<j)))can[k][l]|=1<<j;
if ((k<<1)&(1<<j))if (!((l<<1)&(1<<j)))can[k][l]|=1<<j;
if ((l>>2)&(1<<j))if (!((l>>1)&(1<<j)))can[k][l]|=1<<j;
if ((l<<2)&(1<<j))if (!((l<<1)&(1<<j)))can[k][l]|=1<<j;
if (!(l&(1<<j)))if (k>>1&(1<<j))can[k][l]|=1<<j;
if (!(l&(1<<j)))if (k<<1&(1<<j))can[k][l]|=1<<j;
}
}
}
随即注意到本题空间限制仅
AC Code:
#include <bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
int dp[2][1<<6+1][1<<6+1],can[1<<6+1][1<<6+1];
bool ok[1<<6+1][1<<6+1];
string abc(ll s,ll dep) {
if (dep==2)return s%2?"1":"0";
return abc(s/2,dep+1)+(s%2?"1":"0");
}
int main() {
int n,m;
cin >> n >> m;
for (int k=0; k<=((1<<m)-1); k++) {
for (int l=0; l<=((1<<m)-1); l++) {
for (int j=0; j<m; j++) {
if ((k>>1)&(1<<j))if (!((l>>1)&(1<<j)))can[k][l]|=1<<j;
if ((k<<1)&(1<<j))if (!((l<<1)&(1<<j)))can[k][l]|=1<<j;
if ((l>>2)&(1<<j))if (!((l>>1)&(1<<j)))can[k][l]|=1<<j;
if ((l<<2)&(1<<j))if (!((l<<1)&(1<<j)))can[k][l]|=1<<j;
if (!(l&(1<<j)))if (k>>1&(1<<j))can[k][l]|=1<<j;
if (!(l&(1<<j)))if (k<<1&(1<<j))can[k][l]|=1<<j;
}
}
}
for (int k=0; k<=((1<<m)-1); k++) {
for (int l=0; l<=((1<<m)-1); l++) {
ok[k][l]=1;
for (int j=0; j<m; j++) {
if (l&(1<<j))
if ((k<<2)&(1<<j))
if (!((k<<1)&(1<<j)))
ok[k][l]=0;
if (l&(1<<j))
if ((k>>2)&(1<<j))
if (!((k>>1)&(1<<j)))
ok[k][l]=0;
if (k&(1<<j))
if ((l<<2)&(1<<j))
if (!((l<<1)&(1<<j)))
ok[k][l]=0;
if (k&(1<<j))
if ((l>>2)&(1<<j))
if (!((l>>1)&(1<<j)))
ok[k][l]=0;
}
}
}
for (int k=0; k<=((1<<m)-1); k++)dp[1][0][k]=1;
for (int l=0; l<=((1<<m)-1); l++)
for (int k=0; k<=((1<<m)-1); k++)
if (ok[k][l]) {
dp[0][k][l]+=dp[1][0][k];
dp[0][k][l]%=mod;
}
for (int i=3; i<=n; i++) {
memset(dp[i%2],0,sizeof(dp[i%2]));
for (int j=0; j<=((1<<m)-1); j++) {
for (int l=0; l<=((1<<m)-1); l++) {
for (int k=0; k<=((1<<m)-1); k++) {
if (!ok[k][l])continue;
if (!ok[l][j])continue;
if (can[k][l]&j)continue;
dp[i%2][l][j]+=dp[i%2^1][k][l];
dp[i%2][l][j]%=mod;
}
}
}
}
ll ans=0;
for (int j=0; j<=((1<<m)-1); j++) {
for (int k=0; k<=((1<<m)-1); k++) {
if (ok[j][k]) {
ans+=dp[n%2][j][k];
ans%=mod;
}
}
}
cout << ans;
return 0;
}