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
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:
Misal
Verilmiş misalda k = 2 xüsusi hüceyrə müəyyən edilib.
Yalnız bir yol güclü hüceyrədən keçir.
Yalnız bir yol güclü hüceyrədən keçir.
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:
mod ilə ədədlərin faktoriallarını saxlayır,
factinv bu faktorialların mod ilə əksini saxlayır:
#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ə:
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:
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);
}