有一定难度的一道动态规划的题目。这个题目首先计算palindrom[i][j],其中i表示对应的数据的位数,j表示相应的数据,palindrom[i][j]中记录的就是i位二进制位表示的数据j是否为回文,如果为回文,那么对应的为true,否则对应的为false。在这样一个初始化结束之后,就开始进行动态规划的过程,dp[i][j]表示的是前面i位中最后的k位表示的状态为j时合法串的个数,对状态进行相应的更新即可,具体实现见如下代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
using namespace std;
#define MOD 1000000007
const int MAX = (1 << 11) + 10;
typedef long long LL;
bool palindrom[12][MAX];
LL dp[405][MAX];
class Solve{
public:
int bit[13];
int n, k;
void Init(){
memset(palindrom, false, sizeof(palindrom));
palindrom[1][0] = true;
palindrom[1][1] = true;
bit[0] = 0;
bit[1] = 1;
for (int i = 2; i < 13; i++) bit[i] = bit[i-1] << 1;
for (int i = 2; i <= 11; i++){
int half = i / 2;
int up = (1 << half) - 1;
for (int j = 0; j <= up; j++){
int temp = j;
int R = 0;
for (int j = 1; j <= half; j++) R = (R << 1) + (temp & 1), temp >>= 1;
if (i & 1){//总位数为奇数位
palindrom[i][(j << 1) << half | R] = true;
palindrom[i][(j << 1 | 1) << half | R] = true;
}
else{//总位数为偶数位
palindrom[i][j << half | R] = true;
}
}
}
}
int Cal(int j,int i){
if (j >= bit[k]) j -= bit[k];
return j << 1 | i;
}
void Deal(){
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
LL ans = 0;
int up = (1 << k) - 1;
for (int i = 1; i <= n; i++){
for (int j = 0; j <= up; j++){
if (dp[i - 1][j] == 0) continue;
for (int x = 0; x <= 1; x++){
int state = Cal(j, x);
if (i >= k&&palindrom[k][state]) continue;
if (i >= k + 1 && palindrom[k + 1][j << 1|x]) continue;
dp[i][state] += dp[i - 1][j];
dp[i][state] = dp[i][state] % MOD;
}
}
}
for (int j = 0; j <= up; j++){
ans = (ans + dp[n][j]) % MOD;
}
cout << ans << endl;
}
};
int main(){
int T;
cin >> T;
Solve a;
a.Init();
while (T--){
cin >> a.n >> a.k;
a.Deal();
}
return 0;
}