Verilən problem üçün cavab C_n^{k}~mod~9929 olacaq. Binomial əmsalı modula görə hesablamaq lazımdırsa, hesablamalar zamanı bölmədən qaçmağa çalışacağıq. Bunun üçün C_n^{k} = C_{n - 1}^{k} + C_{n - 1}^{k - 1}, C_n^{0} = 1 formulasından istifadə edəcəyik.
Problemi aşağıdakı formuladan istifadə edərək də həll etmək olar
bölməni modula görə tərs ədədə vurma ilə əvəz edərək, moduluna görə. Qeyd edək ki, sadə ədəddir. Deməli, n / i = n \cdot (i^{-1})~mod~9929.
Fermanın teoreminə görə i^{9928}~mod~9929 = 1 və ya (i \cdot i^{9927})~mod~9929 = 1, buradan moduluna görə -nin tərs ədədi i^{9927}~mod~9929 olacaq. Beləliklə
Algoritminin realizasiyası
Sabitləri və massivini elan edək, burada cnk[n][k] = C_n^{k}~mod~9929.
#define MAX 510
#define MOD 9929
int cnk[MAX][MAX];c funksiyası C_n^{k}~mod~9929 binomial əmsalının dəyərini hesablayır.
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;
}Proqramın əsas hissəsi. massivini sıfırlarla inicializasiya edirik. Giriş məlumatlarını oxuyuruq.
memset(cnk,0,sizeof(cnk));
scanf("%d %d",&n,&k);Hesablayırıq və cavabı çıxarırıq.
printf("%d\n",c(n,k));Algoritmin realizasiyası – dövri
Sabitləri və massivini elan edək, burada cnk[n][k] = C_n^{k}.
#define MAX 502
#define MOD 9929
int cnk[MAX][MAX];FillCnk funksiyası binomial əmsallarla massivini doldurur.
void FillCnk(void)
{
int n, k;
memset(cnk,0,sizeof(cnk));c_nk[n][0] = C_n^{0} = 1 inicializasiyası.
for(n = 0; n < MAX; n++) cnk[n][0] = 1;Hesablamaları aparırıq, C_n^{k} = C_{n - 1}^{k} + C_{n - 1}^{k - 1} formulundan istifadə edərək. Hesablamaları moduluna görə aparırıq.
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;
}Proqramın əsas hissəsi. Binomial əmsallarını massivə doldururuq.
FillCnk();Giriş məlumatlarını oxuyuruq. Hesablayırıq və cavabı çıxarırıq.
scanf("%d %d",&n,&k);
printf("%d\n",cnk[n][k]);Algoritmin realizasiyası – modula görə tərs
pow funksiyası x^n~mod~p hesablayır.
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 funksiyası -ə görə tərs rəqəmi hesablayır, modulu ilə: x^{-1}~mod~p ( sadə).
int inverse(int x, int p)
{
return pow(x, p - 2, p);
}Cnk funksiyası binomial əmsalın dəyərini C_n^{k} moduluna görə hesablayır. Bunun üçün ifadə
şəklində yenidən yazmışıq
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;
}Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.
scanf("%d %d", &n, &k);Hesablayırıq və cavabı çıxarırıq.
res = Cnk(n, k, 9929);
printf("%d\n", res);Java realizasiyası
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 realizasiyası – iterativ, uzun arifmetika
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 realizasiyası
Cnk funksiyası binomial əmsalın dəyərini C_n^{k}~mod~9929 hesablayır və onun dəyərini dp[n][k] hüceyrəsində yadda saxlayır.
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]Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.
n, k = map(int, input().split())Dəyərləri yadda saxlamaq üçün ikiölçülü siyahını inicializasiya edirik:
dp = [[-1] * 501 for _ in range(501)]Hesablayırıq və cavabı çıxarırıq.
print(Cnk(n, k, dp))