1 条题解
-
1
从二进制高位到低位遍历,尝试合并
具体过程如下:
1.对于当前位j,若已合并的段中有奇数个1,那么我们不可能分裂当前合并状态,否则会导致一些更高位变成1,所以没救了,ans+=(1ll<<j)
2.尝试合并后,若发现num1<K,那么没救了,ans+=(1ll<<j)
否则,我们可以采用当前的方案 即另num=num1,异或和数组v[1~ num1]=v1[1~ num1]
#include<bits/stdc++.h> using namespace std; int n,K,num,cnt[80]; long long w[500005],v1[500005],v[500005],ans; void jilu(long long x) { int t=0; while(x){ if(x&1) cnt[t]++; t++;x>>=1; } } int main() { ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); cin>>n>>K; for(int i=1;i<=n;i++){ cin>>v[i];jilu(v[i]); } num=n; for(int j=59;j>=0;j--) { if(cnt[j]==0) continue; bool cmt=0; for(int i=1;i<=num;i++){ if((v[i]>>j)&1) cmt^=1; } if(cmt){ ans+=(1ll<<j);continue; } int num1=0;cmt=0; memset(v1,0,sizeof v1); for(int i=1;i<=num;i++) { if(cmt) v1[num1]^=v[i]; else v1[++num1]^=v[i]; cmt^=((v[i]>>j)&1); } if(num1<K) ans+=(1ll<<j); else{ num=num1; for(int i=1;i<=num1;i++) v[i]=v1[i]; } } cout<<ans; return 0; }记得检查传参类型,不然RE炸50分
对1进行位运算时,记得加ll,不然WA炸50分
- 1
信息
- ID
- 24
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- (无)
- 递交数
- 44
- 已通过
- 8
- 上传者