Відповіддю до задачі буде значення C_n^{k}~mod~9929. Оскільки слід знайти біноміальний коефіцієнт по модулю, постараємося при обчисленнях уникнути ділення. Для цього скористаємося співвідношенням C_n^{k} = C_{n - 1}^{k} + C_{n - 1}^{k - 1}, C_n^{0} = 1.
Задачу можна вирішити також за формулою
замінивши ділення множенням на обернене число по модулю . Зазначимо, що число просте. Тобто n / i = n \cdot (i^{-1})~mod~9929.
За теоремою Ферма i^{9928}~mod~9929 = 1 або (i \cdot i^{9927})~mod~9929 = 1, звідки оберненим до по модулю буде i^{9927}~mod~9929. Таким чином
Реалізація алгоритму
Оголосимо константи і масив , для якого cnk[n][k] = C_n^{k}~mod~9929.
#define MAX 510
#define MOD 9929
int cnk[MAX][MAX];Функція c обчислює значення біноміального коефіцієнта C_n^{k}~mod~9929.
int c(int n, int k)
{
if (cnk[n][k] > 0) return cnk[n][k];
if (n - k < k) return c(n,n-k);
if (!k) return cnk[n][k] = 1;
return cnk[n][k] = (c(n-1,k) + c(n-1,k-1)) % MOD;
}Основна частина програми. Ініціалізуємо масив нулями. Читаємо вхідні дані.
memset(cnk,0,sizeof(cnk));
scanf("%d %d",&n,&k);Обчислюємо і виводимо відповідь.
printf("%d\n",c(n,k));Реалізація алгоритму – циклічна
Оголосимо константи і масив , для якого cnk[n][k] = C_n^{k}.
#define MAX 502
#define MOD 9929
int cnk[MAX][MAX];Функція FillCnk заповнює масив біноміальними коефіцієнтами.
void FillCnk(void)
{
int n, k;
memset(cnk,0,sizeof(cnk));Ініціалізація cnk[n][0] = C_n^{0} = 1.
for(n = 0; n < MAX; n++) cnk[n][0] = 1;Проводимо обчислення, скориставшись формулою C_n^{k} = C_{n - 1}^{k} + C_{n - 1}^{k - 1}. Обчислення проводимо по модулю .
for(n = 1; n < MAX; n++)
for(k = 1; k <= MAX; k++)
cnk[n][k] = (cnk[n-1][k] + cnk[n-1][k-1]) % MOD;
}Основна частина програми. Заповнюємо масив біноміальних коефіцієнтів.
FillCnk();Читаємо вхідні дані. Обчислюємо і виводимо відповідь.
scanf("%d %d",&n,&k);
printf("%d\n",cnk[n][k]);Реалізація алгоритму – обернене по модулю
Функція pow обчислює x^n~mod~p.
int pow(int x, int n, int 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^{-1}~mod~p ( просте).
int inverse(int x, int p)
{
return pow(x, p - 2, p);
}Функція Cnk обчислює значення біноміального коефіцієнта C_n^{k} по модулю . Для цього вираз
перепишемо у вигляді
int Cnk(int n, int k, int p)
{
int res = 1;
if (k > n - k) k = n - k;
for (int i = 1; i <= k; i++)
res = ((res * (n - i + 1)) % p * inverse(i, p)) % p;
return res;
}Основна частина програми. Читаємо вхідні дані.
scanf("%d %d", &n, &k);Обчислюємо і виводимо відповідь.
res = Cnk(n, k, 9929);
printf("%d\n", res);Java реалізація
import java.util.*;
public class Main
{
static int dp[][];
static int MOD = 9929;
static int Cnk(int n, int k)
{
if (n == k) return 1;
if (k == 0) return 1;
if (dp[n][k] != -1) return dp[n][k];
return dp[n][k] = (Cnk(n - 1, k - 1) + Cnk(n - 1, k)) % MOD;
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
int n = con.nextInt();
int k = con.nextInt();
dp = new int[n+1][k+1];
for(int i = 0; i <= n; i++)
Arrays.fill(dp[i],-1);
int res = Cnk(n,k);
System.out.println(res);
con.close();
}
}Java реалізація – ітераційна, довга арифметика
import java.util.*;
import java.math.*;
public class Main
{
static BigInteger Cnk(int n, int k)
{
BigInteger res = BigInteger.ONE;
BigInteger MOD = BigInteger.valueOf(9929);
BigInteger p = BigInteger.valueOf(n);
BigInteger q = BigInteger.valueOf(1);
for (int i = 0; i < k; i++)
{
res = res.multiply(p).multiply(q.modInverse(MOD)).mod(MOD);
p = p.subtract(BigInteger.ONE);
q = q.add(BigInteger.ONE);
}
return res;
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
int n = con.nextInt();
int k = con.nextInt();
BigInteger res = Cnk(n,k);
System.out.println(res);
con.close();
}
}Python реалізація
Функція Cnk обчислює значення біноміального коефіцієнта C_n^{k}~mod~9929 і запам'ятовує його значення в ячейці dp[n][k].
def Cnk(n, k, dp):
if n == k: return 1
if k == 0: return 1
if dp[n][k] != -1: return dp[n][k]
dp[n][k] = (Cnk(n - 1, k - 1, dp) + Cnk(n - 1, k, dp)) % 9929
return dp[n][k]Основна частина програми. Читаємо вхідні дані.
n, k = map(int, input().split())Ініціалізуємо двовимірний список для запам'ятовування значень:
dp = [[-1] * 501 for _ in range(501)]Обчислюємо і виводимо відповідь.
print(Cnk(n, k, dp))