java中的包含和排除主体

时间:2018-04-03 20:58:53

标签: java c++ logic combinatorics discrete-mathematics

您好我想在Java中编码包含和排除主体。 我想为这个问题编码

给定N个素数和一个数M,找出从1到M的数字可被N个给定素数中的任何一个整除。

 The number of integers between 1 and 500 (both inclusive) that are divisible by 3 or 5 or 7 is

 P(3 U 5 U 7) = P(3) + P(5) + P(7) - P(3X5) - P(5X7)- P(3X7)+ P(3X5X7)

 P(3) = 500/3 = 166.66 Take 166 ,
 P(5) = 500/5 = 100 ,
 P(7) = 500/7 = 71.42 Take 71,
 P(3X5) = p(15) = 500/15 = 33.33 Take 33 ,
 P(7X5) = p(35) = 500/35 = 14.28 Take 14,
 P(3X7) = p(21) = 500/21 = 23.8  Take 23,
 P(3X5x7) = p(105 ) = 500/105 = 4.76  Take 4


 Answer = 166+100+71-33-14-23+4 = 271

我正在尝试使用此C ++实现构建Java代码https://www.geeksforgeeks.org/inclusion-exclusion-principle-and-programming-applications/

 int count(int a[], int m, int n)
{
    int odd = 0, even = 0;
    int counter, i, j, p = 1;
    int pow_set_size = (1 << n);


   //this for loop will run 2^n time   
    for (counter = 1; counter < pow_set_size; counter++) {

    //I am not understanding  below for loop code
        p = 1;
        for (j = 0; j < n; j++) {

            /* Check if jth bit in the counter is set
             If set then pront jth element from set */
            if (counter & (1 << j)) {
                p *= a[j];
            }
        }

        // if set bits is odd, then add to
        // the number of multiples
        if (__builtin_popcount(counter) & 1)
            odd += (100 / p);
        else
            even += 100 / p;
    }

    return odd - even;
}

我只是没有得到这个for循环的真正含义

    for (j = 0; j < n; j++) {

        /* Check if jth bit in the counter is set
         If set then pront jth element from set */
        if (counter & (1 << j)) {
            p *= a[j];
        }
    }

和这部分

// if set bits is odd, then add to
        // the number of multiples
        if (__builtin_popcount(counter) & 1)
            odd += (100 / p);
        else
            even += 100 / p;

给出我不理解的解释

  

由奇数个的乘法形成的数字   将添加素数,并通过乘法形成数字   因此,将减去偶数的数字以得到总数   倍数在1到M之间。

请问有人可以帮助我用这个逻辑来实现它吗?

提前致谢:)

1 个答案:

答案 0 :(得分:1)

外部循环用于从输入数组生成所有可能的素因子集。 counter中的每个位代表数组中的位置。

内部循环检查counter中的每个位,如果该位置位,它将数组中相应的素数乘以p,即检查子集的所有素因子的乘积。例如,给定素数数组{3, 5, 7}

counter bits factors            product
1       001  a[0]               3
2       010  a[1]               5
3       011  a[0] * a[1]        15
4       100  a[2]               7
5       101  a[0] * a[2]        21
6       110  a[1] * a[2]        35
7       111  a[0] * a[1] * a[2] 105

C ++内置__builtin_popcount(counter)计算counter中的设置位数。 Java等价物是Integer.bitCount()。它用于测试p中包含的因子的数量是否为奇数(如果是,则结果的低位将被设置......这可以通过其他方式检查,例如if (Integer.bitCount(counter) % 2 == 1))。

最后,计算p小于m的倍数(在您的情况下为500),如果p中的因子数为奇数,则将其添加到包含集中,如果是偶数则排除。

请注意,C ++示例中存在一个错误,它会忽略m参数并使用硬编码值100

在Java中:

public class IncExc {
    public static void main(String[] args) {
        int a[] = {3, 5, 7};
        int m = 500;
        System.out.println(count(a, m));
    }

    static int count(int a[], int m) {
        int odd = 0;
        int even = 0;
        int powSetSize = 1 << a.length;

        // For all sub-sets of elements in the array of primes
        for (int counter = 1; counter < powSetSize; counter++) {
            int p = 1;
            for (int j = 0; j < a.length; j++) {
                // If the jth bit of this combination is set then multiply in the jth element
                if ((counter & (1 << j)) != 0) {
                    p *= a[j];
                }
            }

            // If the number of factors in p is odd, accumulate the count of multiples in our "odd" register
            // Otherwise use the "even" register
            if ((Integer.bitCount(counter) & 1) == 1)
                odd += m / p;
            else
                even += m / p;
        }

        return odd - even;
    }
}