求出给定集合的所有子集的最小公倍数之和

时间:2014-10-20 10:15:38

标签: algorithm computer-science dynamic-programming primes prime-factoring

鉴于:设置A = {a0, a1, ..., aN-1}1 ≤ N ≤ 100),2 ≤ ai ≤ 500

问:查找大小至少为A的所有子集的所有最小公倍数(LCM)的总和。

集合B = {b0, b1, ..., bk-1}的最小公倍数被定义为Bmin的最小整数bi | Bmin,对于所有0 ≤ i < k

示例:

N = 3A = {2, 6, 7},然后:

LCM({2, 6})      =    6
LCM({2, 7})      =   14
LCM({6, 7})      =   42
LCM({2, 6, 7})   =   42
----------------------- +
answer              104

天真的方法是简单地计算所有O(2N)子集的最小公倍数,这对于相当大的N来说是不可行的。


解决方案草图:

问题来自竞赛 * ,它也提供了solution sketch。这就是我的问题所在:我不理解暗示的方法。

解决方案读取(模数一些小的固定语法问题):

  

解决方案有点棘手。如果我们仔细观察,我们会发现整数介于2500之间。因此,如果我们对数字进行素数分解,我们将获得以下最大权力:

 2 8  
 3 5
 5 3
 7 3
11 2
13 2
17 2
19 2
  

除此之外,所有质数都有幂1.因此,我们可以使用这些整数轻松计算所有可能的状态,留下9 * 6 * 4 * 4 * 3 * 3 * 3 * 3个状态,几乎为70000。对于其他整数,我们可以制作如下所示的dp:dp[70000][i],其中i可以是0100。但是,由于dp[i]取决于dp[i-1],因此dp[70000][2]就足够了。这使得n * 70000的复杂性变得可行。

我有以下具体问题:

  • 这些州是什么意思?
  • dp是否代表动态编程?若然,是什么重现关系正在解决?
  • dp[i]如何计算dp[i-1]
  • 为什么大素数对国家数量没有贡献?它们中的每一个都发生01次。对于每个素数,状态数是否应该乘以2(再次导致不可行的状态空间)?

* 原始问题描述可以从this source找到(问题F)。这个问题是该描述的简化版本。

4 个答案:

答案 0 :(得分:3)

社论的第一部分似乎很有用,但第二部分相当含糊(也许没有用;我宁愿完成这个答案而不是弄清楚)。

让我们假设输入由成对不同的素数组成,例如2,3,5和7.然后答案(用于求和所有集合,其中0整数的LCM为1)是

(1 + 2) (1 + 3) (1 + 5) (1 + 7),

因为子集的LCM与此处的乘积完全相同,所以只需将其相乘。

让我们放松素数成对不同的限制。如果我们有一个像2,2,3,3,3和5这样的输入,那么乘法就像

(1 + (2^2 - 1) 2) (1 + (2^3 - 1) 3) (1 + (2^1 - 1) 5),

因为2出现多重性2,而3出现多重性3,而5出现多重性1.对于,例如,只有3的集合,有2^3 - 1种方式来选择包含一个3和1方式来选择空集。

如果它是19或更少,则调用 small ,否则调用 large 。注意,整数500或更少可被最多一个大素数(具有多重性)整除。小素数更有问题。我们要做的是计算LCM的素数因子分解的每个可能的小部分(即~70,000个状态之一),通过丢弃不能除的整数得到的问题的LCM之和这样的LCM并且只留下其他整数的大素数因子(或1)。

例如,如果输入是2,30,41,46和51,状态是2,那么我们将2保留为1,丢弃30(= 2 * 3 * 5; 3和5很小)保留41为41(41为大),保留46为23(= 2 * 23; 23为大),丢弃51(= 3 * 17; 3和17为小)。现在,我们使用前面描述的技术计算LCM的总和。使用inclusion-exclusion去除其小部分正确划分状态而不是完全相等的LCM的子集。也许我稍后会做一个完整的例子。

答案 1 :(得分:3)

讨论

在阅读了实际的比赛描述(page 10 or 11)和解决方案草图之后,我必须得出结论,解决方案草图的作者在写作时非常不精确。

高级问题是如果通过公平硬币投掷随机选择组件,则计算预期寿命。这就是计算所有子集的最小公倍数的原因 - 所有子集都有效地代表了样本空间。您最终可能会得到任何可能的组件。设备的故障时间基于集合的LCM。因此,预期寿命是所有集合的LCM的平均值。

请注意,这应该包括只有一个项目的集合的LCM(在这种情况下,我们假设LCM是元素本身)。解决方案草图似乎破坏了,也许是因为他们以不太优雅的方式处理它。

这些州是什么意思?

草图作者仅使用单词 state 两次,但显然设法切换含义。在第一次使用 state 这个词时,他们似乎在谈论可能选择的组件。在第二次使用中,他们可能会谈论可能的失败时间。他们可能会混淆这个术语,因为他们的动态编程解决方案通过对单词的一次使用来初始化值,并且递归关系源于另一种。

dp是否代表动态编程?

我会说它确实或者它是巧合,因为解决方案草图似乎非常暗示动态编程。

如果是,那么什么是递归关系?如何从dp [i-1]计算dp [i]?

我能想到的是,在他们的解决方案中, state i表示失败的时间T(i),此次失败的次数已被计算在内,dp[i]。得到的总和将是所有dp[i] * T(i)的总和。

然后

dp[i][0]将仅计算第一个组件的失败时间。然后dp[i][1]将计算第一个和第二个组件的失败时间。 dp[i][2]将用于第一,第二和第三。等。

使用零初始化dp[i][0],但dp[T(c)][0](其中c是第一个被考虑的组件)除外,该值应为1(因为此组件的失败时间已被计算一次,因此远)。

dp[i][n]为每个组件dp[i][n-1]填充c

  • 对于每个i,请将dp[i][n-1]复制到dp[i][n]
  • 将{1}添加到dp[T(c)][n]
  • 对于每个i,请将dp[i][n-1]添加到dp[LCM(T(i), T(c))][n]

这是做什么的?假设您知道自己有时间失败j,但是您添加了k失败时间的组件。无论您以前使用过什么组件,新的失败时间都是LCM(j, k)。这是因为对于两组ABLCM(A union B} = LCM(LCM(A), LCM(B))

同样,如果我们考虑T(i)失败的时间以及我们的新组件T(c)失败的时间,则导致失败的时间为{{1} }。请注意,我们将此时间记录为LCM(T(i), T(c))配置失败,因此我们应该在引入新组件后记录许多新的失败时间。

为什么大素数对州的数量没有贡献?

  

每个都发生0或1次。每个素数的状态数是否应该乘以2(再次导致不可行的状态空间)?

当然,你是对的。但是,解决方案草图指出具有大质数的数字以另一种(未指定的)方式处理。

如果我们确实包含它们会发生什么?我们需要表示的的数量会爆炸成一个不切实际的数字。因此,作者对这些数字的解释不同。注意,如果小于或等于500的数字包括大于19的素数,则其他因子乘以21或更小。这使得这些数字适合强暴,不需要任何表格。

答案 2 :(得分:0)

What is meant by these states?

我想在这里,状态指的是数字是否在集合B的{B0,b1,...,bk-1}的集合中。

Does dp stand for dynamic programming and if so, what recurrence relation is being solved?

我相信解决方案草图中的dp代表动态编程。

How is dp[i] computed from dp[i-1]?

我们可以从以前的状态中找出下一组LCM的状态是可行的。所以,我们只需要2的数组,并来回切换。

Why do the big primes not contribute to the number of states? Each of them occurs either 0 or 1 times. Should the number of states not be multiplied by 2 for each of these primes (leading to a non-feasible state space again)?

我们只能使用Prime Factorization和exponents来表示数字。

这是一个例子。

6 =(2 ^ 1)(3 ^ 1)(5 ^ 0) - >州&#34; 1 1 0&#34;代表6 18 =(2 ^ 1)(3 ^ 2)(5 ^ 0) - >州&#34; 1 2 0&#34;代表18

以下是我们如何使用Prime Factorization

获得6和18的LMC

LCM(6,18)=(2 ^(max(1,1))(3 ^(max(1,2))(5 ^ max(0,0))=(2 ^ 1)(3 ^ 2)(5 ^ 0)= 18

2 ^ 9&gt; 500,3 ^ 6> 500,5 ^ 4> 500,7 ^ 4> 500,11 ^ 3> 500,13 ^ 3> 500,17 ^ 3> 500,19 ^ 3> 500

我们只能使用素数2,3,5,7,11,13,17,19的指数计数来表示集B中的LCM = {b0,b1,...,bk-1} 对于给定的集合A = {a0,a1,...,aN-1}(1≤N≤100),其中2≤ai≤500。

9 * 6 * 4 * 4 * 3 * 3 * 3 * 3&lt; = 70000,所以我们只需要两个dp [9] [6] [4] [4] [3] [3] [3] ] [3]以跟踪所有LCM&#39;状态。所以,dp [70000] [2]就足够了。

我把一个小的C ++程序放在一起来说明我们如何得到给定集合A = {a0,a1,...,aN-1}(1≤N≤100)的LCM之和,其中2≤ai ≤500。在解决方案草图中,我们需要循环通过70000最大可能的LCM。

int gcd(int a, int b) {
    int remainder = 0;
    do {
        remainder = a % b;
        a = b;
        b = remainder;
    } while (b != 0);
    return a;
}

int lcm(int a, int b) {
    if (a == 0 || b == 0) {
        return 0;
    }
    return (a * b) / gcd(a, b);
}


int sum_of_lcm(int A[], int N) {

    // get the max LCM from the array
    int max = A[0];
    for (int i = 1; i < N; i++) {
        max = lcm(max, A[i]);
    }
    max++;

    //
    int dp[max][2];
    memset(dp, 0, sizeof(dp));
    int pri = 0;
    int cur = 1;

    // loop through n x 70000
    for (int i = 0; i < N; i++) {
        for (int v = 1; v < max; v++) {
            int x = A[i];
            if (dp[v][pri] > 0) {
                x = lcm(A[i], v);
                dp[v][cur] = (dp[v][cur] == 0) ? dp[v][pri] : dp[v][cur];
                if ( x % A[i] != 0 ) {
                    dp[x][cur] += dp[v][pri] + dp[A[i]][pri];
                } else {
                    dp[x][cur] += ( x==v ) ? ( dp[v][pri] + dp[v][pri] ) : ( dp[v][pri] ) ;
                }
            }
        }
        dp[A[i]][cur]++;
        pri = cur;
        cur = (pri + 1) % 2;
    }

    for (int i = 0; i < N; i++) {
        dp[A[i]][pri] -= 1;
    }
    long total = 0;
    for (int j = 0; j < max; j++) {
        if (dp[j][pri] > 0) {
            total += dp[j][pri] * j;
        }
    }
    cout << "total:" << total << endl;

    return total;
}



int test() {
    int a[] = {2, 6, 7 };
    int n = sizeof(a)/sizeof(a[0]);
    int total = sum_of_lcm(a, n);
    return 0;
}

Output
total:104

答案 3 :(得分:-2)

各州不仅仅是素数的力量。你的数字最多为2 ^ 8,所以2的幂是[0..8],这是9个状态。与其他州类似。

“dp”很适合动态编程,我不确定。

复发关系是问题的核心,因此您将通过自己解决问题来学习更多知识。从一些简单的小例子开始。

对于大素数,尝试在不使用它们(或它们的等价物)的情况下解决减少的问题,然后将它们重新添加以查看它们对最终结果的影响。