Số sô cô la


17

Đưa ra một mbằng nthanh chocolate, m,ntích cực, đầu ra số cách để phá vỡ thanh vào mn1 của 1 mảnh trong đó mỗi ngắt xảy ra trên một Gridline.

Trật tự là quan trọng. Các mảnh cũng có thể phân biệt được, vì vậy hai mảnh ở hai đầu của thanh sô cô la 1 trên 3 không tương đương.

Chẳng hạn, đối với khối 2 x 2, chúng ta có:

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


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


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


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

Do đó, có 4 cách để phá vỡ một thanh sô cô la 2 trên 2.

Quy tắc

  • Đầu vào sẽ là hai số nguyên thông qua chức năng nhập, STDIN, dòng lệnh hoặc tương tự. Xuất ra một số duy nhất, số cách để phá vỡ thanh sô cô la.

  • Vì các con số tăng lên khá nhanh, đừng lo lắng nếu đầu ra vượt quá giới hạn số nguyên của ngôn ngữ của bạn - việc gửi của bạn sẽ hợp lệ miễn là về mặt lý thuyết thuật toán hoạt động cho tất cả các đầu vào có thể.

Các trường hợp thử nghiệm

Đầu ra không phụ thuộc vào thứ tự m,n, vì vậy các trường hợp thử nghiệm được liệt kê sao cho 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 là số sô cô la được sắp xếp theo hình tam giác sao cho mỗi hàng tương ứng với tổng m+n.

Câu trả lời:


7

Toán học, 85 byte

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

Trường hợp thử nghiệm

f[4,4]
(* 63352393728 *)

3

Python 3, 168 , 156 , 147 byte

Đã cải thiện nhờ trò chuyện

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)

Ung dung:

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

Thuật toán được dựa trên bài báo này .

Tôi có lẽ có thể cắt nó xuống nhiều hơn nữa, tôi chỉ không chắc là ở đâu


3

R, 208 198 byte

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]}

Thụt lề, với dòng mới:

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]
}

Sử dụng:

> 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

Về lý thuyết, người ta có thể viết một phiên bản đệ quy ngắn hơn của ca. 160 byte nhưng nó nhanh chóng đạt đến giới hạn đệ quy mặc định và kích thước ngăn xếp bảo vệ mặc định và sửa đổi các mặc định này (sử dụng options(expressions=...)và đối số tương ứng --max-ppsize=) sẽ dẫn đến mã dài hơn mã này.
plannapus

Bạn có thể lưu hai byte bằng cách bỏ qua f=.
Alex A.

2

Python 2, 135 byte

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()])

Đây là những gì tôi nghĩ ra. Nó thực sự chậm, nhưng đây là phiên bản nhanh hơn (cần 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(),))

Ví dụ

$ 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

Giải trình

Mã xác định một hàm Ccó một mảng các mảnh. Thuật toán là như vậy:

  1. for i,Q in enumerate(A): lặp qua mảng các mảnh.
  2. for W,H in(Q,Q[::-1]): tính toán hai lần, xoay 90 độ.
  3. for c in range(1,W): lặp qua các vị trí có thể để phân chia tại.
  4. A[:i]+A[i+1:]+[(c,H),(W-c,H)]: có được một danh sách mà không có phần tách và với hai phần mới.
  5. C(…): gọi lại hàm trong danh sách đó.
  6. sum(…): tổng hợp kết quả cho mỗi lần phân chia có thể.
  7. or 1: nếu không thể chia tách, có chính xác một cách để tách sô cô la.

Cuối cùng, mã được gọi với một mảng chứa đầu vào.


1

ES6, 141 byte

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

Dựa trên công thức được tìm thấy bởi @CameronAasta. Ung dung:

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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.