c++ 枚举两个序列的交集

muk1a3rh  于 2023-06-25  发布在  其他
关注(0)|答案(2)|浏览(161)

我有两个序列:
1.无符号64位数k的倍数,例如k=5{0, 5, 10, 15, 20, 25, ...}

  1. 64位掩码m加上64位常量C的子集,例如m=0b1011{C+0, C+1, C+2, C+3, C+8, C+9, C+10, C+11}。注:Cm不相交,也就是(m & C) = 0
    除了检查k的每一个倍数并检查它是否匹配第二个序列标准,或者检查掩码m的每个子集并与C进行“或”运算,并与k进行除法运算之外,还有其他方法可以枚举这两个序列的所有交集吗?
    64位数P位于这两个序列的交集中,如果P % k == 0(P & C) == C(P & ~(C | m)) = 0
    注意:枚举第二个序列实际上很容易:
  1. uint64_t m = ..., C = ...;
  2. uint64_t subset = 0;
  3. do {
  4. uint64_t value = subset + C;
  5. print(value);
  6. // if (value % 5) => in the intersection of the sequences
  7. subset = (subset - m) & m;
  8. } while (subset != 0);

编辑:枚举的顺序无关紧要
另外:我并不希望把它们都列举出来,但我希望有某种迭代器,我可以总是前进并获得下一个交集

gtlvzcf8

gtlvzcf81#

C mod k是一个常数,这意味着我们正在寻找m的子集,这些子集实现了一个且只有一个值mod k-当与C mod k相加时为零mod k

  1. x = (k - (C mod k)) mod k

作为2的幂的m的每个比特也是常数mod k。因此,任务似乎是枚举那些总和为x mod k的组合。
例如,对于每个看到的组合,通过将当前2的幂添加到m mod k中来生成新的组合。一个直接的优化可以是将2的幂分组在m中,这些幂等于mod k。除此之外,我不知道有什么技巧可以加快这种搜索速度--组合状态的数量mod k可以取决于km

1rhkuytd

1rhkuytd2#

当前的问题是生成一个给定数k的倍数的数,并且满足由两个64位常数mC定义的按位准则。
如果我们用素因子来考虑这个问题,那么我们要寻找的数字是那些以k作为因子的数字,并且其按位表示与给定掩码对齐。如果我们有无穷多个这样的数,它们将均匀分布在数线上,每个数之间的间隔为k
假设k=5m=0b1011C=0。那么k的倍数是{0, 5, 10, 15, 20, 25, ...},掩码m加上C的子集是{0, 1, 2, 3, 8, 9, 10, 11}。两个序列中的数字都是{0, 5, 10}
这里是一个建议的解决方案,它利用逐位操作和基本循环来递增地生成序列中的下一个数字。

  1. class IntersectionGenerator {
  2. private:
  3. uint64_t k, m, C, current_multiple, subset;
  4. public:
  5. IntersectionGenerator(uint64_t k, uint64_t m, uint64_t C) : k(k), m(m), C(C) {
  6. subset = 0;
  7. current_multiple = 0;
  8. }
  9. // Return next intersection
  10. uint64_t next() {
  11. while (true) {
  12. uint64_t potential_value = subset + C;
  13. if ((potential_value % k) == 0) {
  14. subset = (subset - m) & m;
  15. return potential_value;
  16. }
  17. else {
  18. subset = (subset - m) & m;
  19. current_multiple += k;
  20. }
  21. }
  22. }
  23. };

在此实现中,IntersectionGenerator::next()将返回满足条件的下一个数字。while循环将继续进行,直到找到一个k的倍数并满足按位标准的数字。当找到这样一个数字时,它将被返回,并计算m的下一个子集。如果数字不满足条件,则循环继续到下一个子集,并递增k的当前倍数。
该解决方案基于您对类似迭代器的结构的请求,并使用增量计算两个序列交集的方法。如果k相对于m的子集的大小较小,则这将有效地工作。
如果m的子集的集合更大,这将变得低效,因为它需要针对m的所有子集测试k的所有倍数。有n个元素的集合有2^n个子集,所以随着m的大小增加,找到交集所需的迭代次数也会增加。
如果序列非常大,则更有效的解决方案将是预先计算并存储序列,然后应用集合交集算法来找到公共元素。但是,这将需要大量内存,并且不会提供您正在寻找的“迭代器”样式的接口。

展开查看全部

相关问题