标签:src ESS 异或 交换 贪心 存在 nbsp 博客 style
题意:给你n个数,要你求出这n个数异或以后的最大值.
注:线性基的应用
这个题的题意很残暴啊,一看就明白,也知道是线性基,但是还是搞不太懂线性基的意思。。。。。。。。。。。。。。。。
首先给出几个博客讲线性基的:
http://www.cnblogs.com/ljh2000-jump/p/5869991.html
http://blog.csdn.net/qaq__qaq/article/details/53812883
然后我的理解觉得这个有点贪心的感觉,这个的构造方法是从上往下,首先我找到一个在(1<<j)位上为1的数,然后把这个数异或其他的数,首先可以确定一点的是不会影响他高数位的数,因为他高数位的数已经全部变成了1,而该数高数位的数是0,这样异或是不会变的,至于下面为什么这样搞,我也不太清楚,接下来是代码:
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int t,n; 5 ll num[110]; 6 //感觉这有很重的贪心的思想在里面 7 //这样的做法是把每行有1的都保存下来了 8 //那么这样肯定就是最大值了 9 void guess(){ 10 int j=63,i=1;//为什么等于63,因为63是int范围内的最大值 11 while(i<=n&&j>=0){ 12 int r=i;//记录当前行 13 for(int k=i;k<=n;k++){//这个搞可以确定已经处理好的前几行 14 if((num[k]>>j)&1){ //完全变成最大值,可以不用管上面的几个值 15 r=k; 16 break; 17 } 18 } 19 if((num[r]>>j)&1){ 20 if(r!=i){ 21 swap(num[i],num[r]);//如果不是当前为,就交换 22 } 23 for(int k=1;k<=n;k++){ 24 if(i!=k&&((num[k]>>j)&1)&&((num[i]>>j)&1)) //这两个数的当前位j 25 //都应该存在 26 num[k]^=num[i]; 27 } 28 i++;//已经处理好的前几位 29 } 30 j--;//依次下移位置 31 } 32 } 33 34 int main(){ 35 int t; 36 scanf("%d",&t); 37 for(int kase=1;kase<=t;kase++){ 38 scanf("%d",&n); 39 for(int i=1;i<=n;i++) scanf("%lld",&num[i]); 40 guess(); 41 ll ans=0; 42 for(int i=1;i<=n;i++) ans=ans^num[i]; 43 printf("Case %d: %lld\n",kase,ans); 44 } 45 return 0; 46 }
标签:src ESS 异或 交换 贪心 存在 nbsp 博客 style
原文地址:https://www.cnblogs.com/pandaking/p/9998440.html