集合 题解
要求输出方案。
好丧啊...
首先我们可以发现两个pattern...
①(2k)^(2k+1)=1
②(2k)^(2k+1)^(2k+3)^(2k+4)=0
接下来对于k>=4的时候,先把l令为一个大一点的偶数,看一下中间有没有四个。
否则就暴力一波找到有没有三个异或和为0,否则就直接输1。那么我们就枚举这个pattern就可以了。
k=1时显然答案就是l。
k=2时还是要把l变成大一点的偶数,然后如果此时l!=r,那么就直接用第一个pattern输1即可。否则现在就两个数l、r,l为奇数,那么就l^r和l二选一即可。
对于k=3的时候,显然答案也<=1,那么我们能不能构出一个答案为0呢?
考虑这个pattern:
110000000 101111111 011111111
可以发现这个玩意儿是最优的(因为你改第二个不会影响,改第一或第三个只会使区间变大)
如果不能用这个pattern,那就套用k=2的做法就行。
码风略鬼畜...
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <string> #include <vector> #include <set> #include <map> #include <queue> #include <algorithm> #include <sstream> #include <stack> #include <iomanip> using namespace std; typedef long long ll; ll l,r,k,t; ll gll_() { ll ans; scanf("%I64d",&ans); return ans; } #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);} #define gll gll_() int main() { FO(set) t=gll; while(t--) { l=gll, r=gll, k=gll; k=min(k,r-l+1); if(k==1) { cout<<l<<"\n1\n"<<l<<"\n"; continue; } if(k==2) { bool s=l&1; l+=s; if(r-l+1>=2) cout<<1<<"\n2\n"<<l<<" "<<l+1<<"\n"; else { l-=s; if((l^r)>l) cout<<l<<"\n1\n"<<l<<"\n"; else cout<<(l^r)<<"\n2\n"<<l<<" "<<r<<"\n"; } continue; } if(k>=4) { bool s=l&1; l+=s; if(r-l+1>=4) cout<<0<<"\n4\n"<<l<<" "<<l+1<<" "<<l+2<<" "<<l+3<<"\n"; else { l-=s; for(ll a=l;a<=r;a++) { for(ll b=l+1;b<=r;b++) { for(ll c=b+1;c<=r;c++) { if((a^b^c)==0) { cout<<"0\n3\n"<<a<<" "<<b<<" "<<c<<"\n"; goto gg; } } } } cout<<1<<"\n2\n"<<l+1<<" "<<l+2<<"\n"; gg:; } continue; } bool ok=0; for(ll x=1;x<=r;x<<=1) { ll a=x+x*2,b=a-1,c=a^b; if(a<=r&&b<=r&&c<=r&&a>=l&&b>=l&&c>=l);else continue; cout<<0<<"\n3\n"<<a<<" "<<b<<" "<<c<<"\n"; ok=1; break; } if(ok) continue; bool s=l&1; l+=s; if(r-l+1>=2) cout<<1<<"\n2\n"<<l<<" "<<l+1<<"\n"; else { l-=s; if((l^r)>l) cout<<l<<"\n1\n"<<l<<"\n"; else cout<<(l^r)<<"\n2\n"<<l<<" "<<r<<"\n"; } } }