codeforces 460D Little Victor and Set(构造、枚举)
最近的CF几乎都没打,感觉挺水的一个题,不过自己仿佛状态不在,看题解才知道做法。
输入l, r, k (1 ≤ l ≤ r ≤ 1012; 1 ≤ k ≤ min(106, r - l + 1)).
从[l,r]选至多k个数使得选出的数的异或值最小,输出最小异或值和方案。
分类讨论,首先如果r-l+1<=4,枚举集合解决之。
先面讨论r-l+1>=5的情况:
此时有至少5个数可以选择,故至少有连续的4个数满足2x,2x+1,2x+2,2x+3。
k==1时显然方案为{l}。k==2时,显然方案为{2x,2x+1}。k>=4时,显然方案为{2x,2x+1,2x+2,2x+3}。
k==3时再另外考虑:
首先,异或值至多为1(参考k==2)
我们现在来找异或值可否为0。先假设可以,则显然是选3个数。不妨设x>y>z。
111...1111
111...1110
000...0001
显然x,y,z前半部分必定是如上这样的,但由于我们要使得x,y,z尽量靠近,所以x,y,z前半部分必然是如下
11
10
01
之后,每添加一位,有可能是yi=zi=1,xi=0或xi=zi=1,yi=0或xi=yi=1,zi=0。
由于要x,y,z尽量靠近,所以显然采取yi=zi=1,zi=0。
所以x,y,z的二进制形式如下
110...0
101...1
011...1
至此,问题大致解决,剩下的就是些细节问题,问题不大。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | #include <cstdio> #include <cstring> #include <iostream> #include <vector> using namespace std; #define ll long long int cnt( int i){ int ret=0; while (i) i-=i&(-i), ++ret; return ret; } int main(){ ll l,r; int k; while (~ scanf ( "%I64d%I64d%d" ,&l,&r,&k)){ if (r-l+1<5){ int n=r-l+1; ll ansxor=1ll<<60; vector<ll>val; for ( int i=1;i<(1<<n);++i){ ll xx=0; for ( int j=0;j<n;++j) if (i&(1<<j)) xx^=l+j; if (xx<ansxor && cnt(i)<=k){ ansxor=xx; val.clear(); for ( int j=0;j<n;++j) if (i&(1<<j)) val.push_back(l+j); } } printf ( "%I64d\n" ,ansxor); printf ( "%d\n" ,val.size()); for ( int i=0;i<val.size();++i) printf ( "%I64d%c" ,val[i],i==val.size()-1? '\n' : ' ' ); } else if (r-l+1>=5){ if (k==1){ printf ( "%I64d\n1\n%I64d\n" ,l,l); continue ;} if (k==2){ if (l&1) l++; puts ( "1" ); puts ( "2" ); printf ( "%I64d %I64d\n" ,l,l+1); } else if (k>=4){ if (l&1) l++; puts ( "0" ); puts ( "4" ); printf ( "%I64d %I64d %I64d %I64d\n" ,l,l+1,l+2,l+3); } else if (k==3){ ll x=-1,y,z; for (ll i=3;i<=r;i=i<<1){ if ((i^(i-1))>=l){ x=i; y=i - 1; z=i^(i-1); break ; } } if (x!=-1){ puts ( "0" ); puts ( "3" ); printf ( "%I64d %I64d %I64d\n" ,x,y,z); } else { if (l&1) l++; puts ( "1" ); puts ( "2" ); printf ( "%I64d %I64d\n" ,l,l+1); } } } } return 0; } |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步