📜  子集可被m整除

📅  最后修改于: 2021-05-06 08:12:17             🧑  作者: Mango

给定一组非负的不同整数和一个值m,请确定给定集合的子集是否存在可被m整除的子集。
输入约束
集合的大小,即n <= 1000000,m <= 1000

例子:

Input : arr[] = {3, 1, 7, 5};
        m = 6;
Output : YES

Input : arr[] = {1, 6};
        m = 5;
Output : NO

此问题是子集和问题的一种变体。在子集和问题中,我们检查给定的总和子集是否存在,这里我们需要查找是否存在一些总和可被m整除的子集。看到输入约束,看起来典型的DP解决方案将在O(nm)的时间内工作。但是在竞争性编程的严格时间限制中,该解决方案可能会起作用。 DP桌的辅助空间也很大,但这是陷阱。

如果n> m ,则总会有一个子集,其总和可被m整除(这很容易用信鸽原理证明)。因此,我们只需要处理n <= m的情况

对于n <= m,我们创建一个布尔DP表,该表将存储从0到m-1的每个值的状态,这是到目前为止可能遇到的子集总和(模m)。

现在,我们遍历给定数组arr []的每个元素,然后添加(模m)j,其具有DP [j] = true并将所有这样的(j + arr [i])%m可能子集和存储在布尔值中数组temp,在j迭代结束时,我们用temp更新DP表。同样,我们将arr [i]添加到DP中,即DP [arr [i]%m] = true。

最后,如果DP [0]为true,则表示是,则存在一个总和可被m整除的子集,否则为否。

C++
// C++ program to check if there is a subset
// with sum divisible by m.
#include 
using namespace std;
  
// Returns true if there is a subset
// of arr[] with sum divisible by m
bool modularSum(int arr[], int n, int m)
{
    if (n > m)
        return true;
  
    // This array will keep track of all
    // the possible sum (after modulo m)
    // which can be made using subsets of arr[]
    // initialising boolean array with all false
    bool DP[m];
    memset(DP, false, m);
  
    // we'll loop through all the elements of arr[]
    for (int i=0; i


Java
// Java program to check if there is a subset
// with sum divisible by m.
import java.util.Arrays;
  
class GFG {
      
    // Returns true if there is a subset
    // of arr[] with sum divisible by m
    static boolean modularSum(int arr[], 
                                int n, int m)
    {
        if (n > m)
            return true;
      
        // This array will keep track of all
        // the possible sum (after modulo m)
        // which can be made using subsets of arr[]
        // initialising boolean array with all false
        boolean DP[]=new boolean[m];
          
        Arrays.fill(DP, false);
      
        // we'll loop through all the elements
        // of arr[]
        for (int i = 0; i < n; i++)
        {
              
            // anytime we encounter a sum divisible
            // by m, we are done
            if (DP[0])
                return true;
      
            // To store all the new encountered sum
            // (after modulo). It is used to make 
            // sure that arr[i] is added only to 
            // those entries for which DP[j] 
            // was true before current iteration. 
            boolean temp[] = new boolean[m];
            Arrays.fill(temp, false);
      
            // For each element of arr[], we loop 
            // through all elements of DP table 
            // from 1 to m and we add current 
            // element i. e., arr[i] to all those 
            // elements which are true in DP table
            for (int j = 0; j < m; j++)
            {
                  
                // if an element is true in 
                // DP table
                if (DP[j] == true)
                {
                    if (DP[(j + arr[i]) % m] == false)
      
                        // We update it in temp and update
                        // to DP once loop of j is over
                        temp[(j + arr[i]) % m] = true;
                }
            }
      
            // Updating all the elements of temp
            // to DP table since iteration over
            // j is over
            for (int j = 0; j < m; j++)
                if (temp[j])
                    DP[j] = true;
      
      
            // Also since arr[i] is a single 
            // element subset, arr[i]%m is one 
            // of the possible sum
            DP[arr[i] % m] = true;
        }
      
        return DP[0];
    }
      
    //driver code
    public static void main(String arg[])
    {
        int arr[] = {1, 7};
        int n = arr.length;
        int m = 5;
      
        if(modularSum(arr, n, m))
            System.out.print("YES\n");
        else
            System.out.print("NO\n");
    }
}
  
//This code is contributed by Anant Agarwal.


Python3
# Python3 program to check if there is 
# a subset with sum divisible by m.
  
# Returns true if there is a subset
# of arr[] with sum divisible by m
def modularSum(arr, n, m):
  
    if (n > m):
        return True
  
    # This array will keep track of all
    # the possible sum (after modulo m)
    # which can be made using subsets of arr[]
    # initialising boolean array with all false
    DP = [False for i in range(m)]
  
    # we'll loop through all the elements of arr[]
    for i in range(n):
      
        # anytime we encounter a sum divisible
        # by m, we are done
        if (DP[0]):
            return True
  
        # To store all the new encountered sum (after
        # modulo). It is used to make sure that arr[i]
        # is added only to those entries for which DP[j] 
        # was true before current iteration. 
        temp = [False for i in range(m)]
  
        # For each element of arr[], we loop through
        # all elements of DP table from 1 to m and
        # we add current element i. e., arr[i] to
        # all those elements which are true in DP
        # table
        for j in range(m):
          
            # if an element is true in DP table
            if (DP[j] == True):
              
                if (DP[(j + arr[i]) % m] == False):
  
                    # We update it in temp and update
                    # to DP once loop of j is over
                    temp[(j + arr[i]) % m] = True
              
        # Updating all the elements of temp
        # to DP table since iteration over
        # j is over
        for j in range(m):
            if (temp[j]):
                DP[j] = True
  
        # Also since arr[i] is a single element
        # subset, arr[i]%m is one of the possible
        # sum
        DP[arr[i] % m] = True
      
    return DP[0]
  
# Driver code
arr = [1, 7]
n = len(arr)
m = 5
print("YES") if(modularSum(arr, n, m)) else print("NO")
  
# This code is contributed by Anant Agarwal.


C#
// C# program to check if there is
// a subset with sum divisible by m.
using System;
  
class GFG {
      
// Returns true if there is a subset
// of arr[] with sum divisible by m
static bool modularSum(int []arr, int n,
                                  int m)
{
    if (n > m)
        return true;
   
    // This array will keep track of all
    // the possible sum (after modulo m)
    // which can be made using subsets of arr[]
    // initialising boolean array with all false
    bool []DP=new bool[m];
    for (int l=0;l


PHP
 $m) 
        return true; 
  
    // This array will keep track of all 
    // the possible sum (after modulo m) 
    // which can be made using subsets of arr[] 
    // initialising boolean array with all false 
    $DP = Array_fill(0, $m, false);
  
    // we'll loop through all the elements of arr[] 
    for ($i = 0; $i < $n; $i++) 
    { 
        // anytime we encounter a sum divisible 
        // by m, we are done 
        if ($DP[0]) 
            return true; 
  
        // To store all the new encountered sum 
        // (after modulo). It is used to make 
        // sure that arr[i] is added only to those  
        // entries for which DP[j] was true before
        // current iteration. 
        $temp = array_fill(0, $m, false) ;
  
        // For each element of arr[], we loop through 
        // all elements of DP table from 1 to m and 
        // we add current element i. e., arr[i] to 
        // all those elements which are true in DP 
        // table 
        for ($j = 0; $j < $m; $j++) 
        { 
            // if an element is true in DP table 
            if ($DP[$j] == true) 
            { 
                if ($DP[($j + $arr[$i]) % $m] == false) 
  
                    // We update it in temp and update 
                    // to DP once loop of j is over 
                    $temp[($j + $arr[$i]) % $m] = true; 
            } 
        } 
  
        // Updating all the elements of temp 
        // to DP table since iteration over 
        // j is over 
        for ($j = 0; $j < $m; $j++) 
            if ($temp[$j]) 
                $DP[$j] = true; 
  
        // Also since arr[i] is a single element 
        // subset, arr[i]%m is one of the possible 
        // sum 
        $DP[$arr[$i] % $m] = true; 
    } 
  
    return $DP[0]; 
} 
  
// Driver Code
$arr = array(1, 7); 
$n = sizeof($arr); 
$m = 5; 
  
if (modularSum($arr, $n, $m) == true )
    echo "YES\n";
else
    echo "NO\n"; 
  
// This code is contributed by Ryuga
?>


输出:

NO

时间复杂度: O(m ^ 2)
辅助空间: O(m)