luogu P4310 绝世好题
题面传送门
这道\(dp\)还是比较水的
首先考虑设\(f_i\)为以\(a_i\)结尾的最长长度,则向前循环枚举找到适合的转移就可以了,时间复杂度\(O(n^2)\),估计\(80\)分
正解也不是很难想,因为这是位运算,所以我们要找到位运算的性质,\(\&\)的性质就是两个数至少有一个相同位置同为\(1\),那么只要枚举位置转移就好了,设\(s_i\)为结尾的数中二进制第\(i\)位为\(1\)的最大值,那么\(f_i\)只要从\(i\)二进制位上为\(1\)的地方转移就可以了。
代码实现:
#include<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int n,m,a,f,s[39],tot,pus,ans;
int main(){
register int i;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&a);
pus=a;
tot=f=0;
while(pus){
if(pus&1) f=max(s[tot],f);
tot++;
pus>>=1;
}
f++;
pus=a;
tot=0;
while(pus){
if(pus&1) s[tot]=max(s[tot],f);
tot++;
pus>>=1;
}
ans=max(ans,f);
}
printf("%d\n",ans);
}