传送门
preface
考试还是第一次这么顺畅的dp,几分钟就切了。。
分析
数据范围明示O(n3)算法,而且并不需要什么(a+b)>>1的规律。
考虑区间dp。因为a[i]很小所以可以直接枚举答案,设f[i][j][k]表示区间i-j是否能得到答案k,转移就很明显了,f[i][j][((a&b)+(a|b))>>1]=f[i][k][a]|f[k+1][j][b]。最后直接输出就行了,注意a[i]范围是0到7,因为没算0爆炸的兄弟走好。
code
#include<bits/stdc++.h> #define maxn 200 #define ll long long #define reg register using namespace std; int n,a[maxn]; bool f[maxn][maxn][10]; int main() { scanf("%d",&n); for(reg int i=1;i<=n;i++) { scanf("%d",&a[i]); f[i][i][a[i]]=true; } for(reg int l=2;l<=n;l++) { for(reg int i=1;i<=n && i+l-1<=n;i++) { reg int j=i+l-1; for(reg int k=i;k<=j;k++) for(reg int a=0;a<=7;a++) if(f[i][k][a]) for(reg int b=0;b<=7;b++) if(f[k+1][j][b]) { int tmp=((a&b)+(a|b))>>1; f[i][j][tmp]=1; } } } for(reg int i=0;i<=7;i++) if(f[1][n][i]) printf("%d ",i); return 0; }