Distributing Apples
Pista 1
Puede sonar extraño, pero intentemos representar una distribución poniendo a todos los niños y las manzanas en una sola línea.
Pista 2
A partir de la primera pista, deberíamos haber notado que cada distribución se puede representar haciendo que cada niño posea un intervalo de las manzanas. Ahora queda contar de cuántas formas se pueden colocar los niños entre las manzanas.
Solución
Explicación
Para tener una idea más ilustrativa del problema dado, consideremos bolas blancas en una fila. De esas bolas blancas, se eligen para colorearlas de negro como separadores, lo que nos da exactamente segmentos de bolas blancas (posiblemente vacíos). Hay
formas de elegir las bolas a colorear de negro.
Las formas de colorear bolas de negro corresponden a las formas de distribuir esas manzanas a niños, porque la cantidad de bolas blancas en un segmento corresponde a la cantidad de manzanas dadas a un niño.
Implementación
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 1e9 + 7;
const int MAXN = 2e6;
vector<ll> fac(MAXN, 1);
vector<ll> inv(MAXN, 1);
/**
* Calcula x^n módulo m en tiempo O(log p).
* Ver también: https://usaco.guide/gold/modular
*/
ll binpow(ll x, ll n, ll m) {
x %= m;
ll res = 1;
while (n > 0) {
if (n % 2 == 1) { res = res * x % m; }
x = x * x % m;
n /= 2;
}
return res;
}
ll binom(int n, int k) { return fac[n] * inv[k] % MOD * inv[n - k] % MOD; }
int main() {
for (int i = 2; i < MAXN; i++) { fac[i] = i * fac[i - 1] % MOD; }
// Calcular el inverso modular con exponenciación
inv[MAXN - 1] = binpow(fac[MAXN - 1], MOD - 2, MOD);
// Calcular el inverso modular con la definición factorial
for (int i = MAXN - 2; i > 0; i--) { inv[i] = (i + 1) * inv[i + 1] % MOD; }
int n, m;
cin >> n >> m;
cout << binom(n + m - 1, n - 1) << endl;
}import java.io.*;
import java.util.*;
public class DistributingApples {
static final long MOD = (long)1e9 + 7;
static final int MAXN = (int)2e6;
static long[] fac = new long[MAXN];
static long[] inv = new long[MAXN];
/**
* Calcula x^n módulo m en tiempo O(log p).
* Ver también: https://usaco.guide/gold/modular
*/
static long binpow(long x, long n, long m) {
x %= m;
long res = 1;
while (n > 0) {
if (n % 2 == 1) { res = res * x % m; }
x = x * x % m;
n /= 2;
}
return res;
}
static long binom(int n, int k) { return fac[n] * inv[k] % MOD * inv[n - k] % MOD; }
public static void main(String[] args) throws IOException {
fac[0] = fac[1] = 1;
for (int i = 2; i < MAXN; i++) { fac[i] = i * fac[i - 1] % MOD; }
inv[0] = 1;
// Calcular el inverso modular con exponenciación
inv[MAXN - 1] = binpow(fac[MAXN - 1], MOD - 2, MOD);
// Calcular el inverso modular con la definición factorial
for (int i = MAXN - 2; i > 0; i--) { inv[i] = (i + 1) * inv[i + 1] % MOD; }
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
System.out.println(binom(n + m - 1, n - 1));
}
}MOD = int(1e9) + 7
MAXN = int(2e6)
fac: list = [1 for _ in range(MAXN)]
inv: list = [1 for _ in range(MAXN)]
def binpow(x: int, n: int, m: int) -> int:
"""
Calcula x^n módulo m en tiempo O(log p).
Ver también: https://usaco.guide/gold/modular
"""
x %= m
res: int = 1
while n > 0:
if n % 2 == 1:
res = res * x % m
x = x * x % m
n //= 2
return res
def binom(n: int, k: int) -> int:
return fac[n] * inv[k] % MOD * inv[n - k] % MOD
for i in range(2, MAXN):
fac[i] = i * fac[i - 1] % MOD
# Calcular el inverso modular con exponenciación
inv[MAXN - 1] = binpow(fac[MAXN - 1], MOD - 2, MOD)
# Calcular el inverso modular con la definición factorial
for i in reversed(range(1, MAXN - 1)):
inv[i] = (i + 1) * inv[i + 1] % MOD
(n, m) = map(int, input().split())
print(binom(n + m - 1, n - 1))