题意:
求长度是n的二进制串中,不含长度大于等于k的回文串的个数
分析:
dp[i][j][k]表示长度i,后11位状态是j不含长度大于等于k的回文串的个数(因为k最大是10,所把后11位状态压缩,dp[i][j][k]=dp[i-1][j>>1][k]+dp[i-1][j>>1|(1<<10)][k],i-1的低11位就是i的高11位以此转移过来)
预处理出来[1,1<<11)中的最大回文串长度,方便统计。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<11 #define All 1,N,1 #define read freopen("in.txt", "r", stdin) const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; int num[410][15],b[15][1<<11],dp[410][1<<11][15]; int pos[15]; void init(){ b[1][0]=b[1][1]=1; for(int i=2;i<=11;++i){ int cas=(1<<i); for(int j=0;j<cas;++j){ int q=j; for(int k=1;k<=i;++k) { pos[k]=q%2; q/=2; } int f=1; for(int k=1;k<=i/2;++k) if(pos[k]!=pos[i-k+1]){ f=0; break; } if(f) b[i][j]=i; else{ b[i][j]=max(b[i-1][j&((1<<(i-1))-1)],b[i-1][j>>1]); } } } for(int i=1;i<=11;++i) { int cas=(1<<i); for(int j=0;j<cas;++j) for(int k=b[i][j]+1;k<=10;++k) { if(i==11)dp[11][j][k]++; num[i][k]++; } } for(int i=12;i<=400;++i){ for(int j=0;j<(1<<11);++j) for(int k=2;k<=10;++k) { if(b[11][j]>=k) dp[i][j][k]=0; else{ dp[i][j][k]=(dp[i-1][j>>1][k]+dp[i-1][(j>>1)|(1<<10)][k])%mod; num[i][k]=(num[i][k]+dp[i][j][k])%mod; } } } } int main() { init(); int t,n,m; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); printf("%d\n",num[n][m]); } return 0; }
原文:http://www.cnblogs.com/zsf123/p/4909602.html