[9.27模拟] 异或
Posted HLX_Y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[9.27模拟] 异或相关的知识,希望对你有一定的参考价值。
题意:多组询问,每组询问给出一段区间[l,r]和一个数k,要求从[l,r]中选择不多于k个数,使得它们的异或和最小,输出最小的异或和、选取的数的个数,选取的数
题解:
大力分类讨论一波
1、k==1,sum=l
2、k==2,如果r==l+1,则sum=min(l,l^r),否则就是1
3、k==3,答案不会超过1,现在考虑找出三个数使得其异或和为0,设$x=2^{k-1}-1$,$y=2^{k-1}+2^k$,$z=y-1$,枚举k,若能在$[l,r]$中找到这个三个数,则sum=0
4、k==4,若r-l>=4,则若l为偶数,l^(l+1)^(l+2)^(l+3)=0,否则(l+1)^(l+2)^(l+3)^(l+4)=0,若r-l<4,则暴搜枚举子集即可
5、k>=5 sum=0
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #define ll long long 8 #define xx ((1ll<<k)-1) 9 #define yy ((1ll<<(k-1))+(1ll<<k)-1) 10 #define zz ((1ll<<(k-1))+(1ll<<k)) 11 using namespace std; 12 13 int T,a[10]; 14 15 struct Node { 16 int cnt; 17 ll sum,s[10]; 18 }ans; 19 20 void solve(ll l, ll r) { 21 bool flg=0; 22 for(int k=1; zz<=r; k++) { 23 if(xx>=l) { 24 printf("0 3\n%lld %lld %lld\n", (ll)xx,(ll)yy,(ll)zz); 25 flg=1; 26 break; 27 } 28 } 29 if(!flg) { 30 if((l&1ll)==0) printf("1 2\n%lld %lld\n", l,l+1); 31 else printf("1 2\n%lld %lld\n", l+1,l+2); 32 } 33 } 34 35 void cal(Node &res, int deep, ll l) { 36 Node ret; 37 ret.sum=ret.cnt=0; 38 for(int i=1; i<=deep; i++) { 39 if(a[i]) { 40 ret.sum^=(l+i-1); 41 ret.cnt++; 42 ret.s[ret.cnt]=(l+i-1); 43 } 44 } 45 if(ret.sum<res.sum) res=ret; 46 } 47 48 void dfs(int dep, int deep, ll l) { 49 if(dep==deep+1) { 50 bool flg=0; 51 for(int i=1; i<=dep; i++) { 52 if(a[i]!=0) flg=1; 53 } 54 if(!flg) return; 55 cal(ans,deep,l); 56 return; 57 } 58 a[dep]=0,dfs(dep+1,deep,l); 59 a[dep]=1,dfs(dep+1,deep,l); 60 } 61 62 void solve2(ll l, ll r) { 63 ans.sum=1ll<<60,ans.cnt=0; 64 memset(ans.s,0,10); 65 dfs(1,r-l+1,l); 66 printf("%lld %d\n", ans.sum,ans.cnt); 67 for(int i=1; i<ans.cnt; i++) { 68 printf("%lld ", ans.s[i]); 69 } 70 printf("%lld\n", ans.s[ans.cnt]); 71 } 72 73 int main() { 74 scanf("%d", &T); 75 while(T--) { 76 ll l,r; int k; 77 scanf("%lld%lld%d", &l,&r,&k); 78 if(k==1) printf("%lld 1\n%lld\n", l,l); 79 else if(k==2) { 80 if(r==l+1) { 81 if(l<=(l^r)) printf("%lld 1\n%lld\n",l,l); 82 else printf("%lld 2\n%lld %lld\n",l^r,l,r); 83 } 84 else { 85 if((l&1ll)==0) printf("1 2\n%lld %lld\n", l,l+1); 86 else printf("1 2\n%lld %lld\n", l+1,l+2); 87 } 88 } 89 else if(k==3) solve(l,r); 90 else if(k==4) { 91 if(r-l>=4) { 92 if((l&1ll)==0) printf("0 4\n%lld %lld %lld %lld\n", l,l+1,l+2,l+3); 93 else printf("0 4\n%lld %lld %lld %lld\n", l+1,l+2,l+3,l+4); 94 } 95 else solve2(l,r); 96 } 97 else { 98 if((l&1ll)==0) printf("0 4\n%lld %lld %lld %lld\n",l,l+1,l+2,l+3); 99 else printf("0 4\n%lld %lld %lld %lld\n", l+1,l+2,l+3,l+4); 100 } 101 } 102 return 0; 103 }
以上是关于[9.27模拟] 异或的主要内容,如果未能解决你的问题,请参考以下文章
9.27考试 SD_le NOIP模拟题 第三题 建造游乐场题解
LeetCode810. 黑板异或游戏/455. 分发饼干/剑指Offer 53 - I. 在排序数组中查找数字 I/53 - II. 0~n-1中缺失的数字/54. 二叉搜索树的第k大节点(代码片段