D. XOR-gun(思维+前缀异或+暴力)

https://codeforces.com/contest/1457/problem/D


话说这场D吃完饭hack了400+人。

思路:开始看到以为答案只有-1,1,2三种,但是并不是。

构造发现如果连续三位的最高位1位置一样,那么就能1次达到目的。

那么这种情况下的极限是什么呢?

0001

0010

0011

01??

01??

1???

1???

可以看到,在最大值1e9的情况下,当序列里刚好不冲突的时候,有60个数字。剩下进去就必然可以1次。

那么题目就剪枝到60以下了。

考虑两个情况:一个是一个区间直接异或出来波峰或者波谷。(n^2)

另一个是两个连续区间分别异或再合并出来的情况。(n^3)

代码上设置边界a[n+1]=1e18;

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=100;
typedef long long LL;
LL a[maxn];
LL sum[maxn];
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL n;cin>>n;
  if(n>60){
    cout<<"1"<<endl;
    return 0;
  }
  a[n+1]=1e18;
  for(LL i=1;i<=n;i++) cin>>a[i];
  for(LL i=1;i<=n;i++){
    sum[i]=sum[i-1]^a[i];
  }
  LL res=1e18;
  for(LL l=1;l<=n;l++){
    for(LL r=l+1;r<=n;r++){
        LL t=sum[r]^sum[l-1];
        if(t>a[r+1]||t<a[l-1]){
            res=min(res,r-l+1-1);
          ///  debug(res);
        }
    }
  }
  for(LL i=1;i<=n;i++){///[i,j][j+1,k]
    for(LL j=i+1;j<=n;j++){
        for(LL k=j+1;k<=n;k++){
            LL t1=sum[j]^sum[i-1];
            LL t2=sum[k]^sum[j];
            if(t1>t2){
                res=min(res,k-j+1-1+j-i+1-1-1);
            }
        }
    }
  }
  if(res==1e18){
    cout<<"-1"<<endl;
  }
  else cout<<res<<endl;
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/110404960