문제

다음을 안다면 변수 a,b,c,d,e의 가능한 조합은 몇 개나 가능합니까?

a+b+c+d+e = 500

그리고 그것들은 모두 정수이고 >= 0이므로 유한하다는 것을 압니다.

도움이 되었습니까?

해결책

@Torlack, @Jason Cohen:"겹치는 하위 문제"가 있기 때문에 재귀는 나쁜 생각입니다. 즉, 선택한 경우 a ~처럼 1 그리고 b ~처럼 2, 그러면 최대 497이 되어야 하는 3개의 변수가 남습니다.다음을 선택하면 동일한 하위 문제에 도달합니다. a ~처럼 2 그리고 b ~처럼 1.(이러한 우연의 일치 횟수는 숫자가 늘어날수록 폭발합니다.)

이러한 문제를 공격하는 전통적인 방법은 다음과 같습니다. 동적 프로그래밍:하위 문제에 대한 솔루션의 상향식 테이블을 작성합니다("1개 변수의 조합 수는 0이 됩니까?"로 시작). 그런 다음 반복을 통해 구축합니다("변수의 조합 수는 몇 개입니까?"). N 변수가 추가됩니다. 케이?"는 "얼마나 많은 조합이 있는가?"에 대한 해의 합입니다. n-1 변수가 추가됩니다. 제이?" 0 <= 제이 <= 케이).

public static long getCombos( int n, int sum ) {
  // tab[i][j] is how many combinations of (i+1) vars add up to j
  long[][] tab = new long[n][sum+1];
  // # of combos of 1 var for any sum is 1
  for( int j=0; j < tab[0].length; ++j ) {
    tab[0][j] = 1;
  }
  for( int i=1; i < tab.length; ++i ) {
    for( int j=0; j < tab[i].length; ++j ) {
      // # combos of (i+1) vars adding up to j is the sum of the #
      // of combos of i vars adding up to k, for all 0 <= k <= j
      // (choosing i vars forces the choice of the (i+1)st).
      tab[i][j] = 0;
      for( int k=0; k <= j; ++k ) {
        tab[i][j] += tab[i-1][k];
      }
    }
  }
  return tab[n-1][sum];
}
$ time java Combos
2656615626

real    0m0.151s
user    0m0.120s
sys 0m0.012s

다른 팁

귀하의 질문에 대한 답변은 2656615626입니다..

답변을 생성하는 코드는 다음과 같습니다.

public static long getNumCombinations( int summands, int sum )
{
    if ( summands <= 1 )
        return 1;
    long combos = 0;
    for ( int a = 0 ; a <= sum ; a++ )
        combos += getNumCombinations( summands-1, sum-a );
    return combos;
}

귀하의 경우에는 summands 5이고 sum 500입니다.

이 코드는 느립니다..속도가 필요한 경우 결과를 캐시하세요. summand,sum 한 쌍.

나는 당신이 숫자를 원한다고 가정합니다 >=0.네가 원한다면 >0, 루프 초기화를 다음으로 바꾸십시오. a = 1 그리고 루프 조건은 a < sum.나는 또한 당신이 순열을 원한다고 가정합니다 (예 : 1+2+3+4+5 ...을 더한 2+1+3+4+5 등).원하는 경우 for 루프를 변경할 수 있습니다. a >= b >= c >= d >= e.

저는 몇 달 전에 아버지를 위해 이 문제를 해결했습니다. 사용 기간을 연장해 주세요.이는 일회성 문제인 경향이 있으므로 가장 재사용이 가능한 제품을 선택하지 않았습니다.

a+b+c+d = 합계

i = 조합의 수

        for (a=0;a<=sum;a++)
        {
            for (b = 0; b <= (sum - a); b++)
            {
                for (c = 0; c <= (sum - a - b); c++)
                {
                    //d = sum - a - b - c;
                    i++
                }
            }
        }

이것은 화이트보드에 적을 수 있을 만큼 간단하지만 충분히 신중하게 생각하지 않으면 누군가를 넘어지게 할 만큼 복잡하기 때문에 실제로 인터뷰에서 물어볼 수 있는 좋은 질문이 될 것입니다.또한 구현이 상당히 달라지는 두 가지 다른 답변을 얻을 수도 있습니다.

주문 사항
순서가 중요하다면 모든 솔루션은 모든 변수에 대해 0이 나타나는 것을 허용해야 합니다.따라서 가장 간단한 해결책은 다음과 같습니다.

public class Combos {
    public static void main() {
        long counter = 0;

        for (int a = 0; a <= 500; a++) {
            for (int b = 0; b <= (500 - a); b++) {
                for (int c = 0; c <= (500 - a - b); c++) {
                    for (int d = 0; d <= (500 - a - b - c); d++) {
                        counter++;
                    }
                }
            }
        }
        System.out.println(counter);
    }
}

2656615626을 반환합니다.

순서는 중요하지 않습니다
순서가 중요하지 않은 경우 합계가 이미 발견되지 않은 한 0이 가능하지 않은지 확인하면 되므로 솔루션이 그다지 어렵지 않습니다.

public class Combos {
    public static void main() {
        long counter = 0;

        for (int a = 1; a <= 500; a++) {
            for (int b = (a != 500) ? 1 : 0; b <= (500 - a); b++) {
                for (int c = (a + b != 500) ? 1 : 0; c <= (500 - a - b); c++) {
                    for (int d = (a + b + c != 500) ? 1 : 0; d <= (500 - a - b - c); d++) {
                        counter++;
                    }
                }
            }
        }
        System.out.println(counter);
    }
}

2573155876을 반환합니다.

문제를 보는 한 가지 방법은 다음과 같습니다.

첫째, a는 0에서 500 사이의 값이 될 수 있습니다.그러면 b+c+d+e = 500-a가 됩니다.이렇게 하면 문제가 하나의 변수만큼 줄어듭니다.완료될 때까지 반복합니다.

예를 들어, a가 500이면 b+c+d+e=0입니다. 이는 a = 500의 경우 b,c,d 및 e 값의 조합이 하나만 있음을 의미합니다.

a가 300이면 b+c+d+e=200이며, 이는 실제로 원래 문제와 동일한 문제로 변수를 하나만 줄였습니다.

메모:Chris가 지적했듯이 이는 실제로 문제를 해결하려는 끔찍한 방법입니다.

링크 텍스트

실수라면 무한대죠..그렇지 않으면 조금 더 까다롭습니다.

(좋아요, 실수를 컴퓨터로 표현하는 경우 유한한 개수가 있을 것입니다...하지만 그것은 클 것이다!)

다음과 같은 경우 일반 공식이 있습니다.
a + b + c + d = N
그러면 음이 아닌 적분 해의 수는 다음과 같습니다. C(N + number_of_variable - 1, N)

@Chris Conway 답변이 정확합니다.적은 금액에 적합한 간단한 코드로 테스트해봤습니다.

                    long counter = 0;
            int sum=25;

            for (int a = 0; a <= sum; a++) {
                for (int b = 0; b <= sum ; b++) {
                    for (int c = 0; c <= sum; c++) {
                        for (int d = 0; d <= sum; d++) {
                             for (int e = 0; e <= sum; e++) {
                           if ((a+b+c+d+e)==sum) counter=counter+1L;

                             }
                       }
                    }
                }
            }
            System.out.println("counter e "+counter);

수학의 답은 504!/(500!* 4!).

공식적으로 x1+x2+...xk=n의 경우 음수가 아닌 숫자 x1,...xk의 조합 수는 이항 계수입니다.(k-1)-(n+k-1) 요소를 포함하는 집합의 조합입니다.

직관은 (n+k-1) 포인트에서 (k-1) 포인트를 선택하고 선택한 두 포인트 사이의 포인트 수를 사용하여 x1,..xk의 숫자를 나타내는 것입니다.

Stack Overflow에 처음으로 답변을 드려서 수학 버전이 좋지 않아서 죄송합니다.

Just a test for code block

Just a test for code block

    Just a test for code block

네거티브도 포함되나요?무한.

긍정적인 것만 포함하는가?이 경우에는 "정수"라고 부르지 않고 대신 "자연수"라고 부릅니다.이 경우에는 ...저는 이 문제를 실제로 풀 수 없습니다. 풀 수 있으면 좋겠지만 제 수학은 너무 녹슬었습니다.아마도 이 문제를 해결하는 미친 통합적인 방법이 있을 것입니다.나는 주변에 능숙한 수학에 대한 몇 가지 조언을 드릴 수 있습니다.

최종 결과 인 경우 A의 범위는 0에서 x로, b의 범위는 0에서 (x -a), c의 범위는 0에서 (x -a -b), 그리고 e.

대답은 모든 가능성의 합입니다.

Google에서 좀 더 직접적인 공식을 찾으려고 노력하고 있지만 오늘 Google-Fu가 정말 부족합니다...

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top