Вам дана матрица размером n × m, в которой
выделены k специальных ячеек. Необходимо добраться из клетки (1, 1) в клетку (n, m).
Разрешается двигаться только вправо или вниз.
Каждая из k специальных ячеек обладает
определённой силой. i-я специальная ячейка имеет силу pi, и при прохождении через неё вы получаете эту силу.
Требуется найти суммарную силу,
которую можно набрать, рассматривая все возможные пути от (1, 1) до (n, m).
Заметим, что:
·
Сила пути определяется как сумма значений pi всех специальных ячеек, посещённых на этом пути.
·
Обычные ячейки, не являющиеся специальными, имеют силу, равную нулю.
Вход. Первая строка содержит целое число t – количество тестов.
В первой строке каждого теста
заданы три целых числа n, m (1 ≤ n, m
≤ 105) и k (1 ≤ k ≤ 106),
где n ∗ m – размер сетки, а k – количество специальных ячеек.
Каждая из следующих k строк содержит три числа xi, yi (1 ≤ xi ≤
n, 1 ≤ yi ≤ m) и pi
(1 ≤ pi ≤ 105), где (xi,
yi) – координаты специальной
ячейки, а pi – её сила.
Выход. Для каждого теста выведите в отдельной строке суммарную
силу, которую можно набрать. Так как ответ может быть очень большим, выведите
его по модулю 109 + 7.
Пример
входа |
Пример
выхода |
1 2 2 2 1 2 4 2 1 7 |
11 |
комбинаторика
Пусть
ways(x, y) обозначает количество
путей на матрице из клетки (1, 1) в клетку (1 + x, 1 + y). Тогда
ways(x, y) = =
Количество
путей из клетки (1, 1) в клетку (n, m), проходящих через
специальную ячейку (x, y), равно ways(x – 1, y – 1)
* ways(n – x, m – y). Умножив это число на p,
получаем суммарную силу всех путей, проходящих через ячейку (x, y).
Пример
В приведенном примере заданы k
= 2 специальные ячейки.
·
Ровно один путь проходит через ячейку с силой 4.
·
Ровно один путь проходит через ячейку с силой 7.
Таким образом, общая сила равна 4
+ 7 = 11.
Объявим массивы:
·
fact содержит факториалы чисел по модулю MOD,
·
factinv содержит обратные значения к этим факториалам по модулю MOD:
fact[n] = n!
mod 1000000007
factinv[n] = n!
-1 mod 1000000007
#define MAX 800001
ll fact[MAX], factinv[MAX];
Функция pow вычисляет степень числа по модулю: xn 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 находит число, обратное к x по простому модулю p.
Так как p – простое
число, то по малой теореме Ферма выполняется равенство:
xp-1 mod p = 1 для любого
1 ≤ x < p
Его можно переписать в виде (x * xp-2) mod p = 1, откуда
следует, что обратным к x является число xp-2 mod p.
ll inverse(ll x, ll p)
{
return pow(x, p - 2, p);
}
Функция Cnk вычисляет
биномиальный коэффициент по формуле:
=
ll Cnk(int n, int k)
{
return ((fact[n] * factinv[k]) % MOD * factinv[n - k]) % MOD;
}
Функция ways вычисляет
количество путей на решетке размером n × m из клетки (0, 0) в клетку (n, m). Так как любой путь между
этими точками имеет длину n + m и содержит ровно m горизонтальных
сегментов, число путей равно .
ll ways(int n, int m)
{
return Cnk(n + m, m);
}
Основная часть программы. Заполняем массивы факториалов fact и обратных факториалов factinv.
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);
Последовательно обрабатываем tests тестов.
scanf("%d", &tests);
while (tests--)
{
Читаем данные текущего теста.
scanf("%d %d %d", &n, &m, &k);
Суммарную
полученную силу сохраняем в переменной res.
res = 0;
Обрабатываем k специальных ячеек.
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;
}
Выводим ответ для текущего теста.
printf("%lld\n", res);
}