Python

Python задача по комбинаторике

дано число n и k, известно что 0<k<n<20, нужна формула по которой можно вычислить количество способов из K элементов и n количества элементов.
Пример:
input:
4 2
output:
12
нужна формула, или решение где она есть
Если из 4 2 получается 12, это не "сочетание", а "размещение":
A(n, k) = n! / (n-k)! - кол-во вариантов с учётом порядка выбранных элементов.
И решать можно двумя способами.

Через факториалы:
 import math
n, k = map(int, input().split())
print(math.factorial(n) // math.factorial(n - k))
Прямым перемножением только нужных множителей:
 import math 
n, k = map(int, input().split())
print(math.prod(range(n - k + 1, n + 1)))
Almaz Almaz
Almaz Almaz
96 542
Лучший ответ
Для неупорядоченных сочетаний используется следующая формула:
 n! / (k!(n-k)!) 
Для практических вычислений её обычно записывают так:
 n * (n - 1) * ... * (n - k + 1) / k! 
(восклицательный знак - это факториал, если что)
А в качестве k выбирают минимум из k, n - k, т.е. кол-во комбинаций из 10 по 7 рассчитывается как кол-во комбинаций из 10 по 3.

Например, вот так:
 def comb(n, k):
prod = n
for i in range(1, min(k, n - k)): prod = prod * (n - i) // (i + 1)
return prod

n, k = map(int, input("Введите n и k через пробел: ").split())
print("Кол-во сочетаний:", comb(n, k))
comb вычисляет количество сочетаний. Если k > n/2, то вычисляется кол-во сочетаний из n по n-k, которое такое же, но требует меньше вычислений.

И количество сочетаний из 4 по 2 - это 6, а не 12.

Но если в ваших выборках важен порядок элементов, то формула будет другая:
 n! / k! 
(уходит один факториал из знаменателя)
Для вычислений она записывается так:
 n * (n - 1) * ... * (k + 1) 
Тогда из 4 по 2 вы получите свои 12.

Соответствующее решение на Питоне:
 def combOrdered(n, k):
prod = n
for i in range(1, k): prod *= n - i
return prod

n, k = map(int, input("Введите n и k через пробел: ").split())
print("Кол-во упорядоченных сочетаний:", combOrdered(n, k))
Юрий Алямовский P.S. Во втором случае формула
 n! / (n - k)! 
т.к. чем больше k, тем больше вариантов.
Для вычислений:
 n * (n - 1) * ... * (n - k + 1) 
Соответственно, и реализация будет
 for i in range(1, n - k): prod *= n - i 
12 никак не получается


 from math import factorial 

def combination(n, k):
# Calculate n!
n_factorial = factorial(n)
# Calculate k!
k_factorial = factorial(k)
# Calculate (n - k)!
n_minus_k_factorial = factorial(n - k)
# n choose k is n! / (k! * (n - k)!).
return n_factorial // (k_factorial * n_minus_k_factorial)

n = 4
k = 2
# Step 1: n! = 4! = 4 * 3 * 2 * 1 = 24
n_factorial = factorial(n)
# Step 2: k! = 2! = 2 * 1 = 2
k_factorial = factorial(k)
# Step 3: (n - k)! = (4 - 2)! = 2! = 2 * 1 = 2
n_minus_k_factorial = factorial(n - k)
# Step 4: n choose k is n! / (k! * (n - k)!).
# n choose k = 24 / (2 * 2) = 6
result = n_factorial // (k_factorial * n_minus_k_factorial)
print(result)
Юрий Алямовский Бросайте свои видеокурсы. Сочетания никто так не вычисляет, это кошмар, а не реализация.
(k - 1) умножений и столько же делений - это максимум.
Или, если у нас большой запас по разрядности, и мы не хотим делить (деление дорого), то (2k - 3) умножений и 1 деление в конце.