K special cells#11455

Let ways(x, y) denote the number of paths on a grid from cell to cell (1 + x, 1 + y). Then

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

The number of paths from cell to cell that pass through a special cell is equal to ways(x - 1, y - 1) \cdot ways(n - x, m - y). Multiplying this number by gives the total power of all paths passing through cell .

It remains to sum the powers of all paths passing through the special cells. The answer will be equal to the sum:

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

Example

In the given example, k = 2 special cells are specified.

Thus, the total power is 4 + 7 = 11.

Algorithm implementation

Declare the arrays:

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

The pow function computes the power of a number modulo : 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;
}

The inverse function finds the number that is the modular inverse of with respect to a prime modulo . Since is a prime number, by Fermat's Little Theorem the following holds:

x^{p-1}~mod~p~=~1~для~любого~1~\le~x~<~p

This can be rewritten as (x \cdot x^{p-2})~mod~p = 1, from which it follows that the modular inverse of is x^{p-2}~mod~p.

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

The Cnk function computes the binomial coefficient using the formula:

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

The ways function calculates the number of paths on an n \times m grid from cell to cell . Since any path between these points has length n + m and contains exactly horizontal steps, the number of paths is equal to C_{n+m}^m.

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

The main part of the program. Fill the arrays of factorials and inverse factorials 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);

Process the tests sequentially.

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

Read the data for the current test.

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

Store the total obtained power in the variable .

  res = 0;

Process the special cells.

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

Print the answer for the current test.

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