【问题标题】:Maximum xor among all subsets of an array数组的所有子集之间的最大异或
【发布时间】:2015-03-13 22:10:28
【问题描述】:

我必须在数组子集的元素中找到异或的最大值。我必须检查数组的每个子集,而产生最大异或的子集就是答案。

例如 -F(S) 表示对数组 P 的子集 S 的所有元素进行异或的函数={1,2,3,4}

F({1,2}) = 3
F({1,3}) = 2
F({1,2,3}) = 0  
F({1,4}) = 5
F({2,3}) = 1  
F({2,4}) = 6  
F({3,4}) = 7  
F({2,3,4}) = 5  
F({1,2,3,4}) = 4`  

它们的最大值是 7。因此答案是 7。(还有其他子集,但不值得考虑)。如果您要告诉我Gaussian Elimination 方法,我在 MSE 的某个地方读到过,但我并不清楚。 如果高斯消除是唯一的答案,请向我详细说明,或者是否有一些我不知道的方法/算法?

【问题讨论】:

  • 子集 {1,2,4} = 7 不是要考虑吗?
  • 数组P的元素有什么特殊的属性吗?
  • @justmscs 没有特殊属性。
  • @AliAkber 你也可以考虑一下。我的意思是答案仍然是 7。

标签: algorithm


【解决方案1】:

您需要的是高斯消除。

例如:3 数字{9, 8, 5}

先按降序排序,再转成二进制:

9 : 1001
8 : 1000
5 : 0101

观察第一个数字。最高位为 4。
现在检查 1st 数字 (9) 的 4th 位。因为它是 1,所以将第 4 位为 1 的数字与其余数字异或。

9 : 1001
1 : 0001 > changed
5 : 0101

现在检查2nd 数字 (1) 的 3rd 位。因为它是 0,所以检查下面的其余数字,其中 3rd 位是 1。
数字 5 在3rd 位中有 1。交换它们:

9 : 1001
5 : 0101 > swapped
1 : 0001 >

现在 xor 5 与 3rd 位为 1 的其余数字。这里不存在。所以不会有任何变化。

现在检查3rd 数字 (1) 的 2nd 位。因为它是 0,并且在第 2 位为 1 的位置下面没有其他数字,所以不会有任何变化。

现在检查 3rd 数字 (1) 的 1st 位。因为它是 1,所以更改 1st 位为 1 的其余数字。

8 : 1000 > changed
4 : 0100 > changed
1 : 0001

不用再考虑了:)

现在异或整个剩余数组{8 ^ 4 ^ 1} = 13

所以13 是解决方案:)

这就是使用高斯消元法解决问题的方法 :)

这是我的 C++ 实现:

#include <bits/stdc++.h>
using namespace std;

typedef long long int           ll;
typedef unsigned long long int  ull;

ull check_bit(ull N,int POS){return (N & (1ULL<<POS));}

vector<ull>v;
ull gaussian_elimination()
{
    int n=v.size();
    int ind=0;  // Array index
    for(int bit=log2(v[0]);bit>=0;bit--)
    {
        int x=ind;
        while(x<n&&check_bit(v[x],bit)==0)
          x++;
        if(x==n)
          continue; // skip if there is no number below ind where current bit is 1
        swap(v[ind],v[x]);
        for(int j=0;j<n;j++)
        {
            if(j!=ind&&check_bit(v[j],bit))
                v[j]^=v[ind];
        }
        ind++;
    }
    ull ans=v[0];
    for(int i=1;i<n;i++)
      ans=max(ans,ans^v[i]);
    return ans;
}
int main()
{
    int i,j,k,l,m,n,t,kase=1;
    scanf("%d",&n);
    ull x;
    for(i=0;i<n;i++)
    {
        cin>>x;
        v.push_back(x);
    }
    sort(v.rbegin(),v.rend());
    cout<<gaussian_elimination()<<"\n";
return 0;
}

【讨论】:

  • 如何修改它以获得最小值?
【解决方案2】:

我猜你指的是this问题。

高斯消元法是我期望从数学网站得到的算法描述。这就是算法在 Python 中的样子。

def max_xor(iterable):
    array = list(iterable)  # make it a list so that we can iterate it twice
    if not array:  # special case the empty array to avoid an empty max
        return 0
    x = 0
    while True:
        y = max(array)
        if y == 0:
            return x
        # y has the leading 1 in the array
        x = max(x, x ^ y)
        # eliminate
        array = [min(z, z ^ y) for z in array]

【讨论】:

  • 是的,我指的是那个问题。你能告诉我这个 python 实现中发生了什么吗?
  • @johnkeets 查找数组中最重要的一位。最大 XOR 设置了该位。使用 XOR 将其设置为最大 XOR 并在数组的其余部分中将其清除,然后解决较小的子问题。
  • 这一步在做什么 --> array = [min(z, z ^ y) for z in array]
  • @Ray 在array = list(iterable) 之后添加行array = [(z &lt;&lt; len(array)) | (1 &lt;&lt; i) for (i, z) in enumerate(array)],它本质上与en.wikipedia.org/wiki/… 中的单位矩阵相邻。然后在最后,包含x 的元素的索引由x 的底部len(array) 位指示。
  • @Ray 当输入限制为 64 位时,最多有 64 个枢轴元素(y 的选择)。代替 n 个低位,我们可以以几乎相同的方式使用 64 个低位,除了它们不是索引到原始数组中,而是索引到枢轴列表中。我们没有预先邻接单位矩阵,而是在使用它减少数组的其余部分之前在 y 上设置适当的位。
猜你喜欢
  • 1970-01-01
  • 2021-01-25
  • 2014-11-16
  • 2018-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多