目录
好久没上 51 nod 刷题了,今天看到一道题,名字叫“绝世好题”,于是就想挑战一下
(做完后想看一下洛谷里头有没有,结果真查到了,题目是一样的)
题目传送门
(洛谷)
绝世好题 - 洛谷https://www.luogu.com.cn/problem/P4310
普通算法
算法解析
刚开始一看,这不就最长上升子序列改个判断吗,于是我迷之自信勇猛的试了一下
首先用 f[i] 表示下从 1 到 i 的符合题目要求的最长的长度
注意要先把他们都赋成 1
于是找从 i - 1 到 1 的和他按位与不是 0 中的最长的,然后把它连到这条最长的上面,即 f[i] 等于前面最长的再加 1
最后再找一下最大的就可以了
代码
具体代码如下
#include <iostream>
#include <string.h>
#define N 100005
using namespace std;
int n, a[N], f[N], maxx, ans;
int main() {
memset(f, 1, sizeof(f));
cin >> n;
for(int i = 1; i <= n; ++i) {
maxx = 0;
cin >> a[i];
for(int j = 1; j < i; ++j)
if((a[j] & a[i]) && (f[j] > maxx))
maxx = f[j];
f[i] = maxx + 1;
if(f[i] > ans)
ans = f[i];
}
cout << ans << endl;
return 0;
}
提交结果
( ・ω・)丿提交一下哈~
Why ? ! 动态规划还能超时?!
AC 算法
算法解析
先来分析一下题目中的 “bi & bi - 1 ≠ 0” 是什么意思
先说一下按位与 ‘&’ 是什么意思
就是每一位都是,1 & 1 = 1,1 & 0 = 0,0 & 1 = 0,0 & 0 = 0
比如:
1 0 1 1 0 1 0 1 0
& 1 0 0 1 1 0 0 1 1
------------------------------
1 0 0 1 0 0 0 1 0
那么 “bi & bi - 1 ≠ 0” 的意思就是两个数的二进制至少有一位(同一位)都是 1
因此我们可以用 f[i] 记录第 i 位能连多少个 1,最后找最大的输出就可以了
每输入一个,就看他哪位是 1(假设第 i 位是 1),然后找所有 i 中最大的 f[i],将所有是 1 的位置对应的 f 都赋成那个最大的再加 1,因为一个 1 能连上,整个数就都能连上,所以里面所有的 1 就都能连上了
因为整形变量只有 32 位,所以 f 数组开 32 位就行了
怎么看他哪位是 1 呢,就枚举 0 到 31(j),然后看他要是 & 1 左移 j 位(1 后面 j 个 0)是 1 的话,就说明他第 j 位是 1,这样做的时间复杂度为 O(64n),应该能过
代码
代码如下:
#include <iostream>
#include <algorithm>
#define N 100005
using namespace std;
long long n, a[N], f[32], maxx, ans;
int main() {
cin >> n;
for(int i = 1; i <= n; ++i) {
maxx = 0;
cin >> a[i];
for(int j = 0; j < 32; ++j)
if(a[i] & (1 << j))
maxx = max(f[j], maxx);
for(int j = 0; j < 32; ++j)
if(a[i] & (1 << j))
f[j] = maxx + 1;
}
for(int i = 0; i < 32; ++i)
if(f[i] > ans)
ans = f[i];
cout << ans << endl;
return 0;
}
提交结果
提交一下~
终于 AC 了!
尾声
如果这篇博客对您(您的团队)有帮助的话,就帮忙点个赞,加个关注!
最后,祝您(您的团队)在 OI 的路上一路顺风!!!
┬┴┬┴┤・ω・)ノ Bye~Bye~