초콜릿 숫자


17

을 감안 m하여 n초콜릿 바, m,n에 줄을 깰 수있는 방법의 긍정적, 출력 수를 mn각 구분은 눈금 선에 발생하는 1 일에 의해 조각.

순서가 중요합니다. 조각도 구별 가능하므로 1 x 3 초콜릿 바의 양쪽 끝에있는 두 조각은 동일하지 않습니다.

예를 들어 2 x 2 블록의 경우 다음이 있습니다.

 _ _            _   _            _   _            _   _
|_‖_|    ->    |‗| |_|    ->    |_| |‗|    ->    |_| |_|
|_‖_|          |_| |_|           _  |_|           _   _
                                |_|              |_| |_|


 _ _            _   _            _   _            _   _
|_‖_|    ->    |_| |‗|    ->    |‗| |_|    ->    |_| |_|
|_‖_|          |_| |_|          |_|  _            _   _
                                    |_|          |_| |_|


 _ _            _ _              _   _            _   _
|‗|‗|    ->    |_‖_|      ->    |_| |_|    ->    |_| |_|
|_|_|           _ _               _ _             _   _
               |_|_|             |_‖_|           |_| |_|


 _ _            _ _               _ _             _   _
|‗|‗|    ->    |_|_|      ->     |_‖_|    ->     |_| |_|
|_|_|           _ _              _   _            _   _
               |_‖_|            |_| |_|          |_| |_|

따라서 2 x 2 초콜릿 바를 분해하는 4 가지 방법이 있습니다.

규칙

  • 입력은 함수 입력, STDIN, 명령 행 또는 이와 유사한 두 개의 정수입니다. 초콜릿 바를 분해하는 여러 가지 방법으로 단일 숫자를 출력하십시오.

  • 숫자가 매우 빠르게 올라가므로 출력이 언어의 정수 한계를 초과하더라도 걱정하지 마십시오. 이론적으로 알고리즘이 가능한 모든 입력에 대해 작동하는 한 제출은 유효합니다.

테스트 사례

출력은의 순서에 의존하지 않으므로 m,n테스트 사례는 다음과 같이 나열됩니다 m <= n.

1 1 -> 1
1 2 -> 1
1 3 -> 2
1 4 -> 6
1 5 -> 24
1 10 -> 362880

2 2 -> 4
2 3 -> 56
2 4 -> 1712
2 5 -> 92800
2 10 -> 11106033743298560

3 3 -> 9408
3 4 -> 4948992
3 5 -> 6085088256
3 10 -> 76209753666310470268511846400

4 4 -> 63352393728

A261964 는 각 행이 합과 일치하도록 삼각형으로 배열 된 초콜릿 숫자 m+n입니다.

답변:


7

수학, 85 바이트

f=If[##==1,1,Tr[Sum[Binomial[1##-2,i#-1]f[i,#]f[#2-i,#],{i,#2-1}]&@@@{{##},{#2,#}}]]&

테스트 사례

f[4,4]
(* 63352393728 *)

3

파이썬 3, 168 , 156 , 147 바이트

채팅 덕분에 개선

f=lambda n:n<1or n*f(n-1);a=lambda m,n,c=lambda m,n:sum(f(m*n-2)/f(i*n-1)/f((m-i)*n-1)*a(i,n)*a(m-i,n)for i in range(1,m)):+(m+n<4)or c(m,n)+c(n,m)

언 골프 드 :

f=lambda n:n<1or n*f(n-1) # Factorial
def a(m, n):
    if m+n < 4:
        return 1
    first = 0
    for i in range(1,m):
        first += f(m*n-2) * 1/f(i*n-1) * 1/f((m-i)*n-1) * a(i,n) * a(m-i,n)
    second = 0
    for i in range(1,n):
        second += f(m*n-2) * 1/f(i*m-1) * 1/f((n-i)*m-1) * a(i,m) * a(n-i,m)
    return first + second

알고리즘은 이 논문 을 기반으로 했다 .

아마 더 많이 줄일 수있을 것입니다.


3

R, 208 198 바이트

f=function(m,n){g=function(i,j){a=0;if(j>1)for(x in 2:j-1)a=a+choose(j*i-2,x*i-1)*M[x,i]*M[j-x,i];a};s=max(m,n);M=matrix(1,s,s);for(i in 1:s)for(j in 1:s)if(i*j>2)M[i,j]=M[j,i]=g(i,j)+g(j,i);M[m,n]}

줄 바꿈으로 들여 쓰기 :

f = function(m,n){
    g=function(i,j){
        a = 0
        if(j>1) for(x in 2:j-1) a = a + choose(j*i-2,x*i-1) * M[x,i] * M[j-x,i]
        a
    }
    s = max(m,n)
    M = matrix(1,s,s)
    for(i in 1:s) for(j in 1:s) if(i*j>2) M[i,j] = M[j,i] = g(i,j) + g(j,i)
    M[m,n]
}

용법:

> f(3,1)
[1] 2
> f(3,2)
[1] 56
> f(3,3)
[1] 9408
> f(4,3)
[1] 4948992
> f(5,3)
[1] 6085088256

이론적으로 ca의 짧은 재귀 버전을 작성할 수 있습니다. 160 바이트이지만 기본 재귀 제한과 기본 보호 스택 크기에 빠르게 도달하고 이러한 기본값 (각각 options(expressions=...)및 인수 사용)을 수정하면 --max-ppsize=이보다 더 긴 코드가 생성됩니다.
plannapus

를 생략하여 2 바이트를 절약 할 수 있습니다 f=.
Alex A.

2

파이썬 2, 135 바이트

C=lambda A:sum(C(A[:i]+A[i+1:]+[(c,H),(W-c,H)])for i,Q in enumerate(A)for W,H in(Q,Q[::-1])for c in range(1,W))or 1
print C([input()])

여기에 내가 생각해 낸 것이 있습니다. 정말 느리지 만 여기에 더 빠른 버전이 있습니다 ( repoze.lru 필요 ).

from repoze.lru import lru_cache
C=lru_cache(maxsize=9999)(lambda A:sum(C(tuple(sorted(A[:i]+A[i+1:]+((c,H),(W-c,H)))))for i,Q in enumerate(A)for W,H in(Q,Q[::-1])for c in range(1,W))or 1)
print C((input(),))

$ time python2 chocolate.py <<< 2,5
92800

real    0m2.954s
user    0m0.000s
sys     0m0.015s

$ time python2 chocolate-fast.py <<< 3,5
6085088256

real    0m0.106s
user    0m0.000s
sys     0m0.015s

설명

이 코드는 C일련의 조각을 취하는 함수 를 정의합니다 . 알고리즘은 다음과 같습니다.

  1. for i,Q in enumerate(A): 조각 배열을 반복합니다.
  2. for W,H in(Q,Q[::-1]): 90도 회전하는 방법을 두 번 계산합니다.
  3. for c in range(1,W): 분할 가능한 위치를 반복합니다.
  4. A[:i]+A[i+1:]+[(c,H),(W-c,H)]: 분할 조각이없고 두 개의 새로운 조각으로 목록을 가져옵니다.
  5. C(…): 해당 목록에서 함수를 다시 호출하십시오.
  6. sum(…): 가능한 각 분할에 대한 결과를 합산합니다.
  7. or 1: 분할이 불가능한 경우 초콜릿을 분리하는 방법은 정확히 있습니다.

마지막으로 코드는 입력을 포함하는 배열로 호출됩니다.


1

ES6, 141 바이트

c=(m,n)=>(f=n=>n<2||n*f(n-1),h=(m,n)=>[...Array(m-1)].reduce((t,_,i)=>t+f(m*n-2)/f(++i*n-1)/f((m-i)*n-1)*c(i,n)*c(m-i,n),0),h(m,n)+h(n,m))||1

@CameronAavik에서 찾은 공식을 기반으로합니다. 언 골프 드 :

function fact(n) {
    return n < 2 ? 1 : n * f(n - 1);
}
function half(m, n) {
    total = 0;
    for (i = 1; i < m; i++)
        total += fact(m * n - 2) / fact(i * n - 1) / fact((m - i) * n - 1) * choc(i, n) * choc(m - i, n)
    return total;
}
function choc(m, n) {
    total = half(m, n) + half(n, m);
    if (!total) total = 1;
    return total;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.