cf 1457D. XOR-gun(异或运算,前缀和,暴力,二进制)

题目链接:https://codeforces.ml/contest/1457/problem/D

题意:给定一个长度为n(2<=n<=1e5)的不减数组a(a[i]<=a[i+1])。1<=ai<=1e9。每次可以执行操作:选择两个相邻的数组去掉这个数,然后在原来位置加上这两个数的异或结果。

问最少经过多少次能够使这个数组不满足不减数组。

题解:分析

1.二进制,如果任意三个连续的数最高位数相同,那么一定可以取依次异或(后面两个数)使这个数组不满足条件。ans=1;

这种情况只需要暴力一遍就可以排序,除了这种情况最坏的情况就是::数组位数:1 1 2 2 .... k k(k为可能的最高位数,一定不超过30,因为1e9<2^30)。

2.另外,加入答案为cnt。那么最后处理两段连续的数组(否则就不想关联了,这里需要理解一下)。

3.然后考虑暴力cnt。见代码注释吧。

#include <bits/stdc++.h>

#define ll long long
#define ld double
#define pi acos(-1)
#define pb push_back
#define mst(a, i) memset(a, i, sizeof(a))
#define pll pair<ll, ll>
#define fi first
#define se second
#define mp(x, y) make_pair(x, y)
#define rep(i, a, n) for (ll i = a; i <= n; i++)
#define per(i, n, a) for (ll i = n; i >= a; i--)
#define dbg(x) cout << #x << "===" << x << endl
#define dbgg(l, r, x)                                                          \
    for (ll i = l; i <= r; i++)                                                \
        cout << x[i] << " ";                                                   \
    cout << "<<<" << #x;                                                       \
    cout << endl
using namespace std;

template <class T> void read(T &x) {
    T res = 0, f = 1;
    char c = getchar();
    while (!isdigit(c)) {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (isdigit(c)) {
        res = (res << 3) + (res << 1) + c - '0';
        c = getchar();
    }
    x = res * f;
}
inline void print(ll x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) print(x / 10);
    putchar(x % 10 + '0');
}
const ll maxn = 1e5 + 10;
const ll mod = 1e9 + 7;

ll n, a[maxn];
ll sum[maxn];
int main() {
    ll _s = 1;
    // read(_s);
    for (ll _ = 1; _ <= _s; _++) {
        read(n);
        mst(a, 0);
        rep(i, 1, n) read(a[i]), sum[i] = sum[i - 1] ^ a[i];
        ll b, c, cnt = 0;
        ll l, r;
        while (1) {
            ++cnt;//暴力讨论cnt
            rep(i, 1, n) {
                rep(j, 1, cnt) {
                    //第一段(i,i+j)操作j次
                    if (i + j <= n) {
                        b = sum[i + j] ^ sum[i - 1];
                        //与前面一个数相比
                        if (i - 1 >= 1 && b < a[i - 1]) {
                            cout << cnt << endl;
                            return 0;
                        }
                        //与后面一个数比
                        if (i + j + 1 <= n && b > a[i + j + 1]) {
                            cout << cnt << endl;
                            return 0;
                        }
                    }
                    //第二段(i+j+1,i+j+1+(cnt-j))操作(cnt-j)次
                    r = i + j + 1 + (cnt - j);
                    if (r <= n) {
                        c = sum[r] ^ sum[i + j];
                        if (c < a[i + j]) {
                            cout << cnt << endl;
                            return 0;
                        }
                        if (r + 1 <= n && c > a[r + 1]) {
                            cout << cnt << endl;
                            return 0;
                        }
                    }
                    //前一段与后一段比
                    if (r <= n && b > c) {
                        cout << cnt << endl;
                        return 0;
                    }
                }

                // if(cnt>=n||cnt>=100) break;
            }
            if (cnt >= n || cnt >= 60) break;
        }

        cout << -1 << endl;
    }
    return 0;
}
/*
input:::

output:::

*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值