排除原则的实施

时间:2014-12-11 16:51:11

标签: c++ algorithm

我找到了一个使用exclusion_principle来解决Problem的代码。我理解其中的大部分内容但我无法理解如何应用排除原则,请帮助我理解。

问题 我有一系列元素。每个元素具有高度Hi和颜色Ci。我必须找到元素序列的数量,它们严格按高度增加并包含所有可能的colurs(从1到K)。

我可以通过使用BIT算法找出增加序列的数量,但问题是如何填充第二个条件,即每个序列包含所有可用颜色中的至少一个元素。

示例:(第一列中的高度和第二列中的颜色)

4 3
1 1
3 2
2 2
4 3

两个有效的子序列是(1,2,4)和(1,3,4)

代码:

int res = 0;
  for(int mask = 0; mask < (1 << K); mask ++){
    memset(ft, 0, sizeof ft);
    int tmp = 0;
    for(int i = 0; i < N; i++){
      if((mask >> (C[i] - 1)) & 1){
        dp[i] = 1 + query(H[i] - 1); // BIT Query function
        madd(tmp, dp[i]);
        update(H[i], dp[i]); // BIT update function
      }
    }
    if(__builtin_popcount(mask) % 2 == K % 2){
      madd(res, tmp);
    } else {
      madd(res, mod - tmp);
    }
  }

1 个答案:

答案 0 :(得分:0)

我不完全了解细节,但这是一个大致的想法。

考虑一系列不同的,更简单的问题:

  

取一些适当的现有颜色子集1 ... K.   当你不被允许使用这个颜色子集(但没有义务使用任何颜色)时,可以制作多少合法(根据高度)序列?

要回答这些问题,它很容易使用BIT(binary indexed tree)。

代码表示mask范围内的数字0...2**K的子集(其中2**K计算为1 << K; 0表示完整的颜色集,因此它不应该使用,但见下文)。

要回答原始问题,您必须迭代所有颜色子集,并对结果应用inclusion-exclusion principle。每个单独的结果测量不包含某些颜色的所有序列的集合。因此,所有这些集合的确定恰好具有不包含某种颜色的元素序列。原始问题的答案是这一组的补充。

代码计算完整序列集的大小以及所有其他计算;从概念上讲,它并不属于那里,但在同一循环中计算它是很自然的。