K xüsusi hüceyrə#11455

K xüsusi hüceyrə (Həll təhlili)

Güman edək ki, ways(x, y) matrisdə hüceyrəsindən (1 + x, 1 + y) hüceyrəsinə qədər olan yolların sayını təyin edir. Onda

ways(x, y) = C_{x + y}^x = C_{x + y}^y

hüceyrəsindən hüceyrəsinə qədər xüsusi hüceyrə üzərindən keçən yolların sayı ways(x - 1, y - 1) \cdot ways(n - x, m - y) bərabərdir. Bu sayını ilə çoxaltmaqla, hüceyrəsi üzərindən keçən bütün yolların cəmi gücünü tapırıq.

Xüsusi hüceyrələrdən keçən yolların gücünü toplamaq qalır. Cavab aşağıdakı cəmlə bərabər olacaq:

\sum_{i = 1}^k ways(x_i - 1, y_i - 1) \cdot ways(n - x_i, m - y_i) \cdot p_i

Misal

Verilmiş misalda k = 2 xüsusi hüceyrə müəyyən edilib.

Buna görə də, ümumi güc 4 + 7 = 11 bərabərdir.

Alqoritmın həyata keçirilməsi

Aşağıdakı massivləri elan edək:

fact[n] = n!~mod~1000000007 \\ factinv[n] = n!^{-1}~mod~1000000007
#define MAX 800001
ll fact[MAX], factinv[MAX];

pow funksiyası modül ilə ədədlərin qüvvətini hesablayır: 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 funksiyası ədədinin sadə modüllü əksini tapır. sadə ədəd olduğuna görə, kiçik Fermat teoreminə görə:

x^{p-1}~mod~p~=~1~bütün~1~\le~x~<~p~halında

Bu (x \cdot x^{p-2})~mod~p = 1 şəklində yazıla bilər, bu da -in əksinin x^{p-2}~mod~p olduğunu göstərir.

ll inverse(ll x, ll p)
{
  return pow(x, p - 2, p);
}

Cnk funksiyası binomial əmsalı aşağıdakı formula əsasən hesablayır:

C_n^k = {n! \over k! (n - k)!}
ll Cnk(int n, int k)
{
  return ((fact[n] * factinv[k]) % MOD * factinv[n - k]) % MOD;
}

ways funksiyası n \times m ölçülü şəbəkədə -dan -yə olan yolların sayını hesablayır. Bu nöqtələr arasındakı hər bir yolun uzunluğu n + m-dir və yalnız üfüqi seqmentləri ehtiva edir, buna görə də yolların sayı C_{n+m}^m-dir.

ll ways(int n, int m)
{
  return Cnk(n + m, m);
}

Proqramın əsas hissəsi. Faktoriallar və əks faktoriallar factinv massivlərini doldururuq.

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);

testlərini ardıcıllıqla emal edirik.

scanf("%d", &tests);
while (tests--)
{

Cari testin məlumatlarını oxuyuruq.

  scanf("%d %d %d", &n, &m, &k);

Toplanmış gücü dəyişənində saxlayırıq.

  res = 0;

xüsusi hüceyrələri emal edirik.

  for (i = 0; i < k; i++)
  {
    scanf("%d %d %d", &x, &y, &p);
    res = (res + (ways(x - 1, y - 1) * 
                  ways(n - x, m - y)) % MOD * p) % MOD;
  }

Cari test üçün cavabı göstəririk.

  printf("%lld\n", res);
}