Algorithm 子集和的变化

Algorithm 子集和的变化,algorithm,dynamic-programming,subset,subset-sum,Algorithm,Dynamic Programming,Subset,Subset Sum,给定一个数字数组,我想找出一组数字,它们的和是给定数字的倍数 我知道这是子集和的变化。但问题是一个数字有无穷多个倍数。所以我想不出一个动态的问题解决方案 那么,如何将子集和问题扩展到它呢?尽管每个(非零)数字都有无穷多个倍数,但一个数字只有有限多个倍数小于集合中所有元素的和。换句话说,您可以始终将集合元素之和生成的最大倍数设为上限。这将使您能够使用标准的伪多项式时间DP技术来解决问题 希望这有帮助 子集和的伪多项式DP解决方案使用DP状态: DP(n, s) = Number of ways o

给定一个数字数组,我想找出一组数字,它们的和是给定数字的倍数

我知道这是子集和的变化。但问题是一个数字有无穷多个倍数。所以我想不出一个动态的问题解决方案


那么,如何将子集和问题扩展到它呢?

尽管每个(非零)数字都有无穷多个倍数,但一个数字只有有限多个倍数小于集合中所有元素的和。换句话说,您可以始终将集合元素之和生成的最大倍数设为上限。这将使您能够使用标准的伪多项式时间DP技术来解决问题


希望这有帮助

子集和的伪多项式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数组。

下面是一些代码,用于查找计算总和的方法

公共静态void main(字符串[]args){

Scanner scan=新的扫描仪(System.in);
int n=scan.nextInt();//集合中的元素数
int m=scan.nextInt();//需要计算总和
scan.nextLine();
int[]设置值=新的int[m];
long[]setSplit=新的long[m+1][n+1];

对于(int i=0;iUseful Why?应该足以让您启动?dp状态可以是[index][给定数字的模数]。@PhamTrung我的意思是该链接首先进入无效页面。现在该链接已修复,谢谢。@PhamTrung但它的奇怪用户使用Quora而不是SOKnowledge来自各个来源:)尽管IMO在编程方面享有更高的声誉,但Quora正在快速发展。
    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*/ 
}