思路 :设d[i][j][k][l] 为 第i个位置还有j个炸弹未放置,且(1, i)的位置有k个雷,(3,i)的位置有l个雷,0 <= k, l <= 1时的方案总数,那么i - 1个位置还剩str[i - 1] - '0'-k-l个雷未放置,再按当前剩余j - k - l个未放置的类在i - 1的位置上放置
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
typedef long long ll;
const int maxn = 1e4 + 10;
const int INF = 1e9;
const int mod = 1e8 + 7;
using namespace std;
int T;
char s[maxn];
ll d[maxn][7][2][2];
ll dfs(int i, int j, int up, int down) {
if(i == 0 && j - up - down == 0) return d[i][j][up][down] = 1;
if(i == 0 && j - up - down != 0) return d[i][j][up][down] = 0;
ll &res = d[i][j][up][down];
if(res > -1) return res;
res = 0; j = j - up - down;
if(j < 0 || j > 2) return res;
int nxt = s[i - 1] - '0' - up - down;
if(j == 0) res += dfs(i - 1, nxt, 0, 0);
if(j == 1) res += dfs(i - 1, nxt, 0, 1);
if(j == 1) res = (res + dfs(i - 1, nxt, 1, 0));
if(j == 2) res = (res + dfs(i - 1, nxt, 1, 1));
res %= mod;
return res;
}
int main() {
scanf("%d", &T);
while(T--) {
scanf("%s", s);
int l = strlen(s) - 1, c = s[l] - '0';
memset(d, -1, sizeof(d));
int sign = 1;
for(int i = 0; i <= l; i++) {
if(i == 0 && s[i] > '4') sign = 0;
if(i == l && s[i] > '4') sign = 0;
if(s[i] > '6') sign = 0;
if(i < l && abs(s[i] - s[i + 1]) > 2) sign = 0;
}
ll ans = 0;
if(sign) {
if(c >= 0) dfs(l, c, 0, 0);
if(c >= 1) dfs(l, c, 0, 1);
if(c >= 1) dfs(l, c, 1, 0);
if(c >= 2) dfs(l, c, 1, 1);
for(int i = 0; i < 2; i++) {
for(int j = 0; j < 2; j++) {
if(d[l][c][i][j] == -1) continue;
ans = (ans + d[l][c][i][j]) % mod;
}
}
}
printf("%lld\n", ans);
}
return 0;
}