题意:
给你三个数l,r,s。l,r代表存在区间(l,r),s表示你有多少钱,此时你要取一段连续的数,若你要取x到y,则你要花费的钱为x到y之间的所有值的亦或(即x ^ (x+1) ^ (x+2)…(y-1) ^ y,且x,y均在l,r区间内,x<=y),问能连续取的最大区间长度,若长度为0输出-1。
思路:
首先亦或值是在二进制下的计算,所以可以根据四亦或值为零这个原理来判断:
___00 ^ ___01 ^ ___10 ^ ___11=0(二进制),若取最长则中间所有可以四个连续亦或为0的(如上)都取,此时中间取的都是连续的,而前后两边最多各剩3个,所以只需要一一枚举前后的个数即可。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
int main(){
ll l,r,s;
while(scanf("%lld%lld%lld",&l,&r,&s)==3){
ll sum=0,ans=0;
for(ll i=l;i<=r;i++) sum^=i;
for(int pre=0;pre<=3;pre++){
for(int h=0;h<=3;h++){
ll dns=sum;
for(ll i1=0;i1<pre&&i1+l<=r;i1++){
dns^=l+i1;
}
for(ll i1=0;i1<h&&r-i1>=l;i1++){
dns^=r-i1;
}
if(dns<=s)
ans=max(ans,r-l+1-pre-h);
}
}
if(ans)
printf("%lld\n",ans);
else printf("-1\n");
}
}
扩展 :
cf上也有道题也有用到了___00 ^ ___01 ^ ___10 ^ ___11=0这个结论的一道构造题,链接:codeforces 1208C,(总结这是一道水题,而且我还做过类似的,但因我在现场赛错把连续的读成了任意导致拖延了队友的进度和多发罚时,故写此博客提醒自己多读题/哭)