给定一组正整数元素,找到GCD等于给定数字的子集的数量。
例子:
Input: arr[] = {2, 3, 4}, gcd[] = {2, 3}
Output: Number of subsets with gcd 2 is 2
Number of subsets with gcd 3 is 1
The two subsets with GCD equal to 2 are {2} and {2, 4}.
The one subset with GCD equal to 3 ss {3}.
Input: arr[] = {6, 3, 9, 2}, gcd = {3, 2}
Output: Number of subsets with gcd 3 is 5
Number of subsets with gcd 2 is 2
The five subsets with GCD equal to 3 are {3}, {6, 3},
{3, 9}, {6, 9) and {6, 3, 9}.
The two subsets with GCD equal to 2 are {2} and {2, 6}
强烈建议您最小化浏览器,然后自己尝试。
一个简单的解决方案是生成给定集合的所有子集,并找到每个子集的GCD。
以下是针对小数字的有效解决方案,即所有数字的最大值不是很高。
1) Find the maximum number of given numbers. Let the
maximum be arrMax.
2) Count occurrences of all numbers using a hash. Let
this hash be 'freq'
3) The maximum possible GCD can be arrMax. Run a loop
for i = arrMax to 1
a) Count number of subsets for current GCD.
4) Now we have counts for all possible GCDs, return
count for given gcds.
步骤3.a如何工作?
如何获取给定GCD’i’的子集数量,其中i处于1到arrMax范围内。想法是使用内置的“ freq”步骤2计算i的所有倍数。让i的“ add”倍数存在。所有带有“ add”数字的可能子集的数量将为“ pow(2,add)– 1”,不包括空集。例如,如果给定数组为{2,3,6}且i = 3,则存在3的2的倍数(3和6)。因此,将存在3个子集{3},{3、6}和{6},它们的i倍数是GCD。这些子集还包括{6},它没有3作为GCD,而是3的倍数。因此,我们需要减去这些子集。我们将每个GCD的子集计数存储在另一个哈希图“子集”中。令’sub’为GCD中具有’i’的倍数的子集的数量。当我们正在评估从arrMax到1的计数时,可以直接从subset []获得’i’任意倍数的’sub’值。
以下是上述想法的实现。
C++
// C++ program to count number of subsets with given GCDs
#include
using namespace std;
// n is size of arr[] and m is sizeof gcd[]
void ccountSubsets(int arr[], int n, int gcd[], int m)
{
// Map to store frequency of array elements
unordered_map freq;
// Map to store number of subsets with given gcd
unordered_map subsets;
// Initialize maximum element. Assumption: all array
// elements are positive.
int arrMax = 0;
// Find maximum element in array and fill frequency
// map.
for (int i=0; i=1; i--)
{
int sub = 0;
int add = freq[i];
// Run a loop for all multiples of i
for (int j = 2; j*i <= arrMax; j++)
{
// Sum the frequencies of every element which
// is a multiple of i
add += freq[j*i];
// Excluding those subsets which have gcd > i but
// not i i.e. which have gcd as multiple of i in
// the subset for ex: {2,3,4} cnsidering i = 2 and
// subset we need to exclude are those havng gcd as 4
sub += subsets[j*i];
}
// Number of subsets with GCD equal to 'i' is pow(2, add)
// - 1 - sub
subsets[i] = (1<
Java
// Java program to count
// number of subsets with
// given GCDs
import java.util.*;
class GFG{
// n is size of arr[] and
// m is sizeof gcd[]
static void ccountSubsets(int arr[], int n,
int gcd[], int m)
{
// Map to store frequency
// of array elements
HashMap freq =
new HashMap();
// Map to store number of
// subsets with given gcd
HashMap subsets =
new HashMap();
// Initialize maximum element.
// Assumption: all array
// elements are positive.
int arrMax = 0;
// Find maximum element in
// array and fill frequency
// map.
for (int i = 0; i < n; i++)
{
arrMax = Math.max(arrMax,
arr[i]);
if(freq.containsKey(arr[i]))
{
freq.put(arr[i],
freq.get(arr[i]) + 1);
}
else
{
freq.put(arr[i], 1);
}
}
// Run a loop from max element
// to 1 to find subsets
// with all gcds
for (int i = arrMax; i >= 1; i--)
{
int sub = 0;
int add = 0;
if(freq.containsKey(i))
add = freq.get(i);
// Run a loop for all multiples
// of i
for (int j = 2; j * i <= arrMax; j++)
{
// Sum the frequencies of
// every element which
// is a multiple of i
if(freq.containsKey(i * j))
add += freq.get(j * i);
// Excluding those subsets
// which have gcd > i but
// not i i.e. which have
// gcd as multiple of i in
// the subset for ex: {2,3,4}
// cnsidering i = 2 and
// subset we need to exclude
// are those havng gcd as 4
sub += subsets.get(j * i);
}
// Number of subsets with GCD
// equal to 'i' is Math.pow(2, add)
// - 1 - sub
subsets.put(i, (1 << add) -
1 - sub);
}
for (int i = 0; i < m; i++)
System.out.print("Number of subsets with gcd " +
gcd[i] + " is " +
subsets.get(gcd[i]) + "\n");
}
// Driver program
public static void main(String[] args)
{
int gcd[] = {2, 3};
int arr[] = {9, 6, 2};
int n = arr.length;
int m = gcd.length;
ccountSubsets(arr, n, gcd, m);
}
}
// This code is contributed by shikhasingrajput
Python3
# Python3 program to count number of
# subsets with given GCDs
# n is size of arr[] and m is sizeof gcd[]
def countSubsets(arr, n, gcd, m):
# Map to store frequency of array elements
freq = dict()
# Map to store number of subsets
# with given gcd
subsets = dict()
# Initialize maximum element.
# Assumption: all array elements
# are positive.
arrMax = 0
# Find maximum element in array and
# fill frequency map.
for i in range(n):
arrMax = max(arrMax, arr[i])
if arr[i] not in freq:
freq[arr[i]] = 1
else:
freq[arr[i]] += 1
# Run a loop from max element to 1
# to find subsets with all gcds
for i in range(arrMax, 0, -1):
sub = 0
add = 0
if i in freq:
add = freq[i]
j = 2
# Run a loop for all multiples of i
while j * i <= arrMax:
# Sum the frequencies of every element
# which is a multiple of i
if j * i in freq:
add += freq[j * i]
# Excluding those subsets which have
# gcd > i but not i i.e. which have gcd
# as multiple of i in the subset.
# for ex: {2,3,4} cnsidering i = 2 and
# subset we need to exclude are those
# havng gcd as 4
sub += subsets[j * i]
j += 1
# Number of subsets with GCD equal
# to 'i' is pow(2, add) - 1 - sub
subsets[i] = (1 << add) - 1 - sub
for i in range(m):
print("Number of subsets with gcd %d is %d" %
(gcd[i], subsets[gcd[i]]))
# Driver Code
if __name__ == "__main__":
gcd = [2, 3]
arr = [9, 6, 2]
n = len(arr)
m = len(gcd)
countSubsets(arr, n, gcd, m)
# This code is contributed by
# sanjeev2552
C#
// C# program to count
// number of subsets with
// given GCDs
using System;
using System.Collections.Generic;
class GFG{
// n is size of []arr and
// m is sizeof gcd[]
static void ccountSubsets(int []arr, int n,
int []gcd, int m)
{
// Map to store frequency
// of array elements
Dictionary freq =
new Dictionary();
// Map to store number of
// subsets with given gcd
Dictionary subsets =
new Dictionary();
// Initialize maximum element.
// Assumption: all array
// elements are positive.
int arrMax = 0;
// Find maximum element in
// array and fill frequency
// map.
for (int i = 0; i < n; i++)
{
arrMax = Math.Max(arrMax,
arr[i]);
if(freq.ContainsKey(arr[i]))
{
freq.Add(arr[i],
freq[arr[i]] + 1);
}
else
{
freq.Add(arr[i], 1);
}
}
// Run a loop from max element
// to 1 to find subsets
// with all gcds
for (int i = arrMax; i >= 1; i--)
{
int sub = 0;
int add = 0;
if(freq.ContainsKey(i))
add = freq[i];
// Run a loop for all
// multiples of i
for (int j = 2;
j * i <= arrMax; j++)
{
// Sum the frequencies of
// every element which
// is a multiple of i
if(freq.ContainsKey(i * j))
add += freq[j * i];
// Excluding those subsets
// which have gcd > i but
// not i i.e. which have
// gcd as multiple of i in
// the subset for ex: {2,3,4}
// cnsidering i = 2 and
// subset we need to exclude
// are those havng gcd as 4
sub += subsets[j * i];
}
// Number of subsets with GCD
// equal to 'i' is Math.Pow(2, add)
// - 1 - sub
subsets.Add(i, (1 << add) -
1 - sub);
}
for (int i = 0; i < m; i++)
Console.Write("Number of subsets with gcd " +
gcd[i] + " is " +
subsets[gcd[i]] + "\n");
}
// Driver code
public static void Main(String[] args)
{
int []gcd = {2, 3};
int []arr = {9, 6, 2};
int n = arr.Length;
int m = gcd.Length;
ccountSubsets(arr, n, gcd, m);
}
}
// This code is contributed by Rajput-Ji
输出:
Number of subsets with gcd 2 is 2
Number of subsets with gcd 3 is 1
练习:扩展上述解决方案,以便所有计算都以模1000000007为模,以避免溢出。