给定一组数字,我想找出一组数字,其总和是给定数字的倍数。
我知道这是子集和的变化。但问题是数量有无数倍。所以我无法想到问题的动态问题解决方案。
那么如何将子集求和问题扩展到它呢?
答案 0 :(得分:1)
对子集和的伪多项式DP解决方案使用DP状态:
DP(n, s) = Number of ways of getting a sum of s using first n elements of the set
需要O(ns)时间。如果我想找到d的所有倍数,我只对d的子集和的剩余部分感兴趣。记住模数是分配的。因此,我将DP状态更改为
DP(n, m) = Number of subsets whose sum = m mod d using the first n elements
空间减少到O(nd),时间也减少到O(nd) 在实际伪多项式解决方案中遵循的一个约定是从末端遍历DP阵列,允许您仅使用O(s)空间。这不能在这里完成。您可以做的最好是使用O(2m)内存来存储以前和当前的DP阵列。
答案 1 :(得分:0)
虽然每个(非零)数字的倍数无限多,但只有有限数量的倍数才会小于集合中所有元素的总和。换句话说,您总是可以上限由集合元素之和生成的最大倍数。这应该使您能够使用标准的伪多项式时间DP技术来解决问题。
希望这有帮助!
答案 2 :(得分:0)
以下是查找计算总和值的方法的代码。
public static void main(String [] args){
Scanner scan=new Scanner(System.in);
int n=scan.nextInt();//number of elements in the set
int m=scan.nextInt();//sum needs to be calculated
scan.nextLine();
int[] setValue=new int[m];
long[][] setSplit=new long[m+1][n+1];
for(int i=0;i<m; i++)
{
setValue[i]=scan.nextInt();
}
setSplit[0][0]=1;
//when sum is 0
for(int i=1; i<m+1; i++)
{
setSplit[i][0]=1;
}
//when sum is more than 0 but set element is 0
for(int j=1; j<n+1; j++)
{
setSplit[0][j]=0;
}
int temp=0;
for(int i=1; i<=m; i++)
{
for(int j=1; j<n+1; j++)
{
setSplit[i][j]=setSplit[i-1][j];
if(j>=setValue[i-1])
{
setSplit[i][j]=setSplit[i][j]+setSplit[i][j-setValue[i-1]];
}
}
}
// System.out.println(Arrays.deepToString(setSplit));
System.out.println(setSplit[m][n]);/*this will give number of ways sum can be calculated*/
}