Step 0 前置知识
即 '&'——按位与。
按位与的特性:
因此可以得出题中的最小值:
Step 1 解题思路
因为 考虑使用
的算法。
先输入数据存在数组 中,定义
然后从头开始扫一遍数组 $a$ 一旦发现有 $k$ 个数按位与在一起结果为
时,
,随后继续扫,直到扫到结尾为止。
这时会有两种情况:
1. 最后 $k_n$ 个数按位与后结果大于 ,这时要把最后
个数与
合在一起,最后
;
2. 在数组 中找不到连续的
个数按位与起来等于
,即 数组 $a$ 中不存在任何一种拆分能比数组
全部数按位与起来更小,此时
;
特别注意,别认为 会 TLE,因为题目中有“所有测试用例中
的总和不超过
”这句话,所以不用担心TLE。
Step 2 AC Code
#include <bits/stdc++.h>
using namespace std;
long long T, n, a[200005], sum, t[45], tt[45], k[200005], top = 1,ans;
inline void find(long long x){
long long qwq = 1;
while (x){
if (x & 1) t[qwq] = 1;
x >>= 1,qwq++;
}
}
inline bool jiancha(){
long long ans = 0;
for (int i = 1; i <= 40; i++) if (tt[i] == 1) return false;
return true;
}
int main(){
scanf ("%lld", &T);
while (T--){
scanf ("%lld", &n);
for (int i = 1; i <= n; i++) scanf ("%lld", &a[i]);
memset (k, 0, sizeof(k));
sum = a[1],top = 0;
for (int i = 2; i <= n; i++) sum &= a[i];//判断是否为第二种情况。
if (sum){printf ("1\n");continue;}
for (int i = 1; i <= 40; i++) tt[i] = 1;
for (int i = 1; i <= n; i++){
find(a[i]);
for (int j = 1; j <= 40; j++) if (t[j] == 0) tt[j] = 0;
for (int j = 1; j <= 40; j++) t[j] = 0;
if (jiancha()){
k[++top] = 1;
for (int j = 1; j <= 40; j++) tt[j] = 1;
}
}
ans = 0;
for (int i = 0; i <= n; i++) if (k[i]) ans = i;
printf ("%lld\n", ans);
}
return 0;
}
Step 3 最后警告
十年OI一场空,多测不清见祖宗。