【问题标题】:How does this code count all subsets of a set of positive integers whose sum is even?此代码如何计算总和为偶数的一组正整数的所有子集?
【发布时间】:2013-07-03 16:49:57
【问题描述】:

我在 TopCoder 解决方案中遇到了这段代码,这让我很困惑。有一个正偶数和奇数整数的数组列表。我认为它返回总和为偶模 MOD 的子集的数量。如果列表很大,我相信 MOD 只是为了避免溢出,所以如果你保持数字小于 32,那么我认为你不需要它。

ArrayList l = { ... positive even and odd integers ... };

int dp[] = {1,0};
for (int i = 0; i < l.size(); ++i) {
        int even = dp[0];
        int odd = dp[1];
        if (l.get(i) % 2 == 0) {
                even *= 2;
                odd *= 2;
        } else {
                even += odd;
                odd = even;
        }
        dp[0] = even % MOD;
        dp[1] = odd % MOD;
}
return (dp[0] - 1 + MOD) % MOD;

如果所有整数都是偶数,那么我认为答案是 2^N-1。 但似乎如果至少有一个奇数,答案就变成了 2^(N-1)-1。那正确吗?如果是这样,为什么要跟踪偶数/奇数计数?

【问题讨论】:

    标签: algorithm sum subset


    【解决方案1】:

    这根本不需要迭代程序。假设您的集合有 N 个元素,k 个偶数和 N-k 个奇数。那么,这 k 个偶数并不真正相关;它们的 2^k 个组合中的任何一个,连同具有偶数和的奇数子集,组合成一个偶数和。

    奇数的组合有多少个和是偶数?如果 N-k > 0,则有 2^(N - k - 1) 个。所以,你是对的。这是一个编码问题,而不是数学问题。

    但是给定的算法如下:

    当 N = 0 时,集合只有一个子集:空集,其总和为 0。因此,从 even=1odd=0 开始。现在是归纳步骤:假设前 k 个元素的分区数是 evenodd

    如果第 k+1 个数字是偶数,则第一个 k 的总和为偶数的任何子集都可以附加(或不附加)第 k+1 个元素,使偶数子集的数量加倍。这同样适用于奇数的子集。

    如果第k+1个数是奇数,那么前k个数的和为偶数的任何子集都不会给出任何新的第k+1个数的偶数子集,而前k个数的子集如果附加了第 k+1 个,则总和为奇数的数字给出偶数和。所以,新的even 是旧的evenodd 的总和。同样,新的odd 也是相同的和,所以新的odd 等于新的even

    请注意,even + odd == 2^k 代表所有 k,无论如何。而且,一旦有一个奇数,even == odd 表示该索引以及更高的索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-02
      • 1970-01-01
      • 2011-06-06
      • 2020-01-17
      • 2015-08-22
      • 1970-01-01
      • 2021-10-12
      • 2014-12-19
      相关资源
      最近更新 更多