Codeforces 1457D. XOR-gun(二进制+思维)

Description

Solution
设原始数组为 a a a, 设 b i b_i bi a i a_i ai 的二进制位数
若存在一个 i i i,满足 b i − 1 = b i = b i + 1 b_{i-1} = b_{i} = b_{i+1} bi1=bi=bi+1,则我们只需要将后两个数异或,得到的数一定比 a i − 1 a_{i-1} ai1小(因为最高位变成0了)
若这样的 i i i 不存在,则原始数组的长度一定不超过 2*30 = 60,
我们暴力计算 n ≤ 60 n \leq 60 n60 的情况:
最后的答案数组一定存在两个相邻两个数是严格递减,而这两个数是由原始数组中两个相邻段连续异或而成的
故我们枚举l,r,k, 代表将a[l,k]异或起来以及将a[k+1,r] 异或起来,是否满足两个数递减的关系

复杂度 O ( n 4 ) O(n^4) O(n4),若预处理出前缀异或和则可优化到 O ( n 3 ) O(n^3) O(n3)

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7;
int a[maxn];
int pre[maxn];
int f(int l,int r) {
    if(l > r) return 0;
    return pre[r] ^ pre[l-1];
}
int main() {
    int n;scanf("%d",&n);
    for(int i = 1;i <= n;++i) {
        scanf("%d",&a[i]);
    }
    if(n > 60) {printf("1\n");return 0;}
    int res = maxn;
    for(int i = 1;i <= n;++i) pre[i] = pre[i-1] ^ a[i];
    for(int l = 1;l < n;++l) {
        for(int r = l + 1;r <= n;++r) {
            int d1 = 0,d2 = 0;
            for(int k = l;k < r;++k) {
                d1 = f(l,k), d2 = f(k+1,r);
                if(d1 > d2) res = min(res, (k-l+ r-(k+1)));
            }
        }
    }
    if(res == maxn) res = -1;
    printf("%d\n", res);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值