Порахуйте кількість способів складання кульок у контейнери


9

У цьому завданні вам надається непарна кількість білих кульок і стільки ж чорних кульок. Завдання полягає в тому, щоб порахувати всі способи складання кульок у бункери так, щоб у кожній відрізці було непарне число кожного кольору.

Наприклад, скажімо, у нас є 3 білі кульки. Різні способи:

(wwwbbb)
(wb)(wb)(wb)

для двох різних можливостей.

Якщо у нас є 5 білих куль, то різні способи:

(wwwwwbbbbb)
(wwwbbb)(wb)(wb)
(wwwb)(wbbb)(wb)
(wb)(wb)(wb)(wb)(wb)

Ви можете взяти вхід, який є одним цілим числом, будь-яким способом, який вам подобається. Вихід - це лише одне ціле число.

Ваш код повинен бути досить швидким, щоб ви бачили його повним для 11 білих куль.

Ви можете використовувати будь-яку мову чи бібліотеку, яка вам подобається.


Поясніть, будь ласка, чи може наш вихід бути лише кількістю різних способів? Тобто єдине число як вихід?
orlp

5
Я припускаю, що це від math.stackexchange.com/questions/2736933/… Ви повинні цитувати це @Lembik
qwr

3
Я думаю, вам слід винести критерій швидкості або зробити його більш конкретним. "Досить швидко" занадто розпливчасто.
ділнан

1
Ви знаєте, що користувачі PPCG досить божевільні, що вони скоріше витратять гроші на використання суперкомп'ютера, щоб обчислити його за 11, ніж взяти ще 1 байт? То навіщо витрачати свої гроші? :)
користувач202729

1
(зауваження: функцію P можна обчислити ефективно за допомогою складної формули . Можна також обчислити цю функцію за допомогою відповідної формули.)
user202729

Відповіді:


5

Парі / GP, 81 байт

p=polcoeff;f(n)=p(p(prod(i=1,n,prod(j=1,n,1+(valuation(i/j,2)==0)*x^i*y^j)),n),n)

Для більшої ефективності замініть 1+на 1+O(x^(n+1))+O(y^(n+1))+(перший Oтермін вже дуже допомагає).

Спробуйте в Інтернеті! (раніше 86-байтна версія з парою непотрібних паронів і без p=абревіатури)

Стара версія, 90 байт

f(n)=polcoeff(polcoeff(taylor(1/prod(i=0,n,prod(j=0,n,1-x^(2*i+1)*y^(2*j+1))),x,n+1),n),n)

Для обчислень f(11)потрібен більший розмір стека, повідомлення про помилку підкаже, як його збільшити. Це більш ефективно (але менш golfy) , щоб замінити два , nякі з'являються в якості другого аргументів prodз (n-1)/2.


Для мене працює до 13!

Я думаю, що з версією, що використовує (n-1)/2?
Крістіан Сіверс

Так, хороший момент.

Не цікаво, чи вважаєте ви, що можливо обчислити f (500)?

2
Обчислити f (500) = 214621724504756565823588442604868476223315183681404
Christian Sievers,

7

Python 3, 108 байт

C=lambda l,r,o=():((l,r)>=o)*l*r%2+sum(C(l-x,r-y,(x,y))for x in range(1,l,2)for y in range(1,r,2)if(x,y)>=o)

Рекурсивно перераховує всі набори, переконуючись, щоб не отримати дублікатів, завжди генеруючи набори в порядку. Розумно швидко при запам'ятовуванні використання C = functoools.lru_cache(None)(C), але це не потрібно n = 11.

Телефонуйте, C(num_white, num_black)щоб отримати результат. Перша пара n:

1: 1
3: 2
5: 4
7: 12
9: 32
11: 85
13: 217
15: 539
17: 1316
19: 3146
21: 7374

Щоб створити результати:

def odd_parts(l, r, o=()):
    if l % 2 == r % 2 == 1 and (l, r) >= o:
        yield [(l, r)]

    for nl in range(1, l, 2):
        for nr in range(1, r, 2):
            if (nl, nr) < o: continue
            for t in odd_parts(l - nl, r - nr, (nl, nr)):
                yield [(nl, nr)] + t

Напр. Для (7, 7):

[(7, 7)]
[(1, 1), (1, 1), (5, 5)]
[(1, 1), (1, 1), (1, 1), (1, 1), (3, 3)]
[(1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1)]
[(1, 1), (1, 1), (1, 1), (1, 3), (3, 1)]
[(1, 1), (1, 3), (5, 3)]
[(1, 1), (1, 5), (5, 1)]
[(1, 1), (3, 1), (3, 5)]
[(1, 1), (3, 3), (3, 3)]
[(1, 3), (1, 3), (5, 1)]
[(1, 3), (3, 1), (3, 3)]
[(1, 5), (3, 1), (3, 1)]

Справді дуже приємно.

2

Пітон 3 , 180 172 байти

def f(n):
 r=range;N=n+1;a=[N*[0]for _ in r(N)];R=r(1,N,2);a[0][0]=1
 for i in R:
  for j in R:
   for k in r(N-i):
    for l in r(N-j):a[k+i][l+j]+=a[k][l]
 return a[n][n]

Спробуйте в Інтернеті!

Безпосередня реалізація функції, що генерує. Довгий, але (дещо) ефективний. O (n 4 ) час, O (n 2 ) пам'ять.

Отриманий масив aмістить усі результати всіх розмірів до n, хоча тільки a[n][n]повертається.


Що ваш код обчислює для рівних n, не цікавлячись? Як у [4] [4].

Це і найшвидше рішення поки що!

2
@Lembik a [4] [4] = Кількість способів покласти 4 білих кулі та 4 чорних кулі у відрі, кожен контейнер має непарну кількість білих кульок і непарну кількість чорних кульок. Так само, як і у визначенні.
користувач202729

1

Пітон 2 ,168 181 байт

from itertools import*
r,p=range,product
def f(n):
 a,R=eval(`[[0]*n]*n`),r(1,n,2);a[0][0]=1
 for i,j in p(R,R):
  for k,l in p(r(n-i),r(n-j)):a[k+i][l+j]+=a[k][l]
 return a[-1][-1]

Спробуйте в Інтернеті!


Це фрагмент (припускає, що він nмістить вхідні дані) Вам слід або додати, def f(n):або n=input()(щоб зробити його функцією / повною програмою відповідно)
user202729

І ... це Python 2, ви можете використовувати вкладку замість двох пробілів. Зберігає байт. aМоже бути eval(`[[0]*n]*n`)(де `позначає repr).
користувач202729
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.