N位x包含L 1s

时间:2014-04-24 19:56:48

标签: c++ algorithm bit-manipulation combinatorics

是否有任何快速算法可以存储包含L位1的所有各种N位数?提供N和L参数。它是在课堂上破解加密系统的,我注意到有两个定时攻击,我可以找到比特长度(N)和1比特(L)的数量。

而不是强制降低下限和上限之间的所有值,而是最小化我需要测试的元素。因此,我正在考虑使用一个包含所有元素的向量,它可能适合我从2个定时攻击中获得的信息。

任何提示都将非常感激。

我正在使用C ++。

2 个答案:

答案 0 :(得分:4)

Bit Twiddling Hacks页面显示了如何使用每个生成的数字的O(1)工作枚举正好n位设置的所有二进制数。他们的解决方案在此重印:

  

假设我们在整数中有一个N位设置为1的模式,我们想要   字典意义上的N 1位的下一个排列。对于   例如,如果N为3且位模式为00010011,则为下一个模式   将是00010101,00010110,00011001,00011010,00011100,00100011,   等等。以下是计算下一个的快速方法   排列。

unsigned int v; // current permutation of bits
unsigned int w; // next permutation of bits

unsigned int t = v | (v - 1); // t gets v's least significant 0 bits set to 1

// Next set to 1 the most significant bit to change,
// set to 0 the least significant ones, and add the necessary 1 bits.
w = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
     

x86 CPU的__builtin_ctz(v) GNU C编译器内在函数返回尾随零的数量。如果您使用Microsoft编译器   x86,内在为_BitScanForward。这些都发出一个bsf   指令,但其他架构可能有等效的指令。   如果没有,那么考虑使用其中一种方法来计算   前面提到的连续零位。这是另一个版本   由于它的除法运算符,它往往会变慢,但事实并非如此   要求计算尾随零。

unsigned int t = (v | (v - 1)) + 1;
w = t | ((((t & -t) / (v & -v)) >> 1) - 1);

从除了最后L位(全1)之外的所有0的数字开始,你应该能够使用它来枚举你想要的所有数字。

希望这有帮助!

答案 1 :(得分:2)

该死的... templatetypedef得到的答案可能比我的好。我写了一个递归算法来生成它们。可能不是你想要的方式,但似乎有效(免责声明:最低限度的测试!)。

我会留在这里为后代,即使它可能不是实现这一目标的最佳方式。与其他答案不同,这个答案将为您提供包含所有可能组合的向量。显然,如果你有数百万/数十亿的组合,这不是一个理想的方法!但是,我想写一个算法来做这件事很有趣。所以任务完成了。

#include <bitset>
#include <vector>
using namespace std;

const int N = 4;

void addValues(int to_add, int start_pos, bitset<N> const& working, vector<bitset<N>>& values)
{
  // Take all of our possible spots
  for (int i = start_pos; i < N && i <= N - to_add; ++i) {
    auto working_copy(working);
    working_copy[i] = 1;

    // We have more bits to set...
    if (to_add > 1) {
      addValues(to_add - 1, i + 1, working_copy, values);
    } 
    // We've set all the bits, so this is a working combination
    else {
      values.push_back(working_copy);
    }
  }
}

int main(int argc, char* argv)
{
  int L = 2;

  vector<bitset<N>> values;
  bitset<N> working;
  addValues(L, 0, working, values);

  return EXIT_SUCCESS;
}