На місць деякі види будуть представлені двома лемурами, а деякі одним. Нехай вибрано пар лемурів (тобто видів представлені двома особами). Зробити такий вибір можна C_k^i способами. Після цього у VIP зоні залишиться n - 2i вільних місць. Ці місця можна зайняти лемурами з k - i залишкових видів, вибираючи по одному лемуру з кожного. Кількість способів вибрати таких лемурів обчислюється за формулою C_{k - i}^{n - 2i}.
Так як значення може приймати будь-яке ціле значення від до , отримуємо підсумкову відповідь як суму по всім можливим :
Приклад
Розглянемо другий приклад, в якому є k = 4 пари лемурів і n = 3 місця у VIP-зоні. За формулою отримуємо:
Випишемо тільки ненульові доданки. Значення C_n^k будемо вважати рівним нулю, якщо виконується одна з трьох нерівностей: k < 0, n < 0 або k > n.
Позначимо лемурів літерами \{a, a, b, b, c, c, d, d\}, де однакові літери відповідають лемурам одного виду.
Доданку C_4^0 \cdot C_4^3 = 4 відповідає ситуація, коли жодна пара лемурів одного виду не обрана, тобто кожен з трьох вибраних лемурів належить до різних видів. Можливі чотири вибірки такі:
Розглянемо доданок C_4^1 \cdot C_3^1 = 12. У цьому випадку з одного виду обираються два лемура (існує варіанти такого вибору). На залишкове одне місце вибирається один лемур з трьох залишкових видів. Таким чином, всього можливо різних варіантів:
Очевидно, що розмістити на місцях по два лемура з двох різних видів неможливо. Тому всі інші доданки суми дорівнюють нулю.
Реалізація алгоритму
Оголосимо константи.
#define MAX 1000001
#define MOD 1000000007Оголосимо масиви:
містить факторіали чисел за модулем ;
factinv містить значення, обернені факторіалам чисел за модулем :
fact[n] = n! mod 1000000007
factinv[n] = n! -1 mod 1000000007
typedef long long ll;
ll fact[MAX], factinv[MAX];Функція pow обчислює ступінь числа за модулем: x^n~mod~p.
ll pow(ll x, ll n, ll p)
{
if (n == 0) return 1;
if (n % 2 == 0) return pow((x * x) % p, n / 2, p);
return (x * pow(x, n - 1, p)) % p;
}Функція inverse знаходить число, обернене за простим модулем . Оскільки — просте число, за малою теоремою Ферма виконується рівність:
Це рівність можна переписати у вигляді:
звідки випливає, що оберненим до є число x^{p-2}~mod~p.
ll inverse(ll x, ll p)
{
return pow(x, p - 2, p);
}Функція Cnk обчислює значення біноміального коефіцієнта за наступною формулою:
ll Cnk(int n, int k)
{
return ((fact[n] * factinv[k]) % MOD * factinv[n - k]) % MOD;
}Основна частина програми. Читаємо вхідні дані.
scanf("%d %d", &k, &n);Заповнюємо масиви факторіалів і factinv.
fact[0] = 1;
for (i = 1; i < MAX; i++)
fact[i] = (fact[i - 1] * i) % MOD;
factinv[0] = 1;
for (i = 1; i < MAX; i++)
factinv[i] = inverse(fact[i], MOD);Обчислюємо відповідь за формулою \sum_{i = 0}^k C_k^i \cdot C_{k - i}^{n - 2i}. Значення біноміального коефіцієнта C_n^k вважаємо рівним нулю, якщо виконується одна з трьох умов: k < 0, n < 0 або k > n.
res = 0;
for (i = 0; i <= k; i++)
{
if (n - 2 * i < 0 || k - i < 0 || n - 2 * i > k - i) continue;
res = (res + Cnk(k, i) * Cnk(k - i, n - 2 * i)) % MOD;
}Друкуємо відповідь.
printf("%lld\n", res);