3700. Number of ZigZag Arrays II
Difficulty: Hard
Topics: Principal, Math, Dynamic Programming, Weekly Contest 469
You are given three integers n, l, and r.
A ZigZag array of length n is defined as follows:
- Each element lies in the range
[l, r]. - No two adjacent elements are equal.
- No three consecutive elements form a strictly increasing or strictly decreasing sequence.
Return the total number of valid ZigZag arrays.
Since the answer may be large, return it modulo 10⁹ + 7.
A sequence is said to be strictly increasing if each element is strictly greater than its previous one (if exists).
A sequence is said to be strictly decreasing if each element is strictly smaller than its previous one (if exists).
Example 1:
- Input: n = 3, l = 4, r = 5
- Output: 2
-
Explanation:
- There are only 2 valid ZigZag arrays of length
n = 3using values in the range[4, 5]:[4, 5, 4][5, 4, 5]
- There are only 2 valid ZigZag arrays of length
Example 2:
- Input: n = 3, l = 1, r = 3
- Output: 10
-
Explanation:
- There are 10 valid ZigZag arrays of length
n = 3using values in the range[1, 3]:-
[1, 2, 1],[1, 3, 1],[1, 3, 2] -
[2, 1, 2],[2, 1, 3],[2, 3, 1],[2, 3, 2] -
[3, 1, 2],[3, 1, 3],[3, 2, 3]
-
- All arrays meet the ZigZag conditions.
- There are 10 valid ZigZag arrays of length
Example 3:
- Input: n = 10000000, l = 1, r = 75
- Output: 852283716
Constraints:
3 <= n <= 10⁹1 <= l < r <= 75
Hint:
- Use matrix exponentiation
- Encode states in a vector of length
2*mwherem = r - l + 1: firstmentries = "next compare = down" for values, nextm= "next compare = up". - Build a transition matrix
T(size2*m × 2*m): from anup,xstate go todown,yfor everyy > x, and fromdown,xgo toup,yfor everyy < x. - Use fast matrix exponentiation to compute
T⁽ⁿ⁻¹⁾, apply it to the initial vector (ones in the block for startingupand separately for startingdown), sum final entries, and add both results (forn=1returnm).
Solution:
We are implementing a solution for counting ZigZag arrays of length up to 10⁹ using matrix exponentiation, based on state transitions between "up" and "down" patterns.
We model each array position as either an "up" transition (next element is greater) or a "down" transition (next element is smaller). The values are shifted to 0..m-1 for indexing. A transition matrix of size 2m × 2m is built where:
- From a down state at value
x, we can go to an up state at anyy > x. - From an up state at value
x, we can go to a down state at anyy < x.
We initialize vectors for starting with either up or down, raise the transition matrix to the power n-1, multiply, and sum all resulting states. The answer is the total number of valid sequences.
Approach
-
State encoding:
- First
mstates: "down" (last move was down, so next must be up). - Next
mstates: "up" (last move was up, so next must be down). - Each state includes the last value
x.
- First
-
Transition rules:
- From
down[x]→up[y]for ally > x(strictly increasing). - From
up[x]→down[y]for ally < x(strictly decreasing). - Adjacent equal values are disallowed by construction.
- From
-
Initialization:
- Start with
down[i] = 1(sequence of length 1, next must be up). - Start with
up[i] = 1(sequence of length 1, next must be down).
- Start with
-
Matrix exponentiation:
- Compute
T⁽ⁿ⁻¹⁾using fast exponentiation (binary exponentiation). - Multiply the resulting matrix by each initial vector.
- Sum all entries from both results to get the total count modulo
10⁹+7.
- Compute
-
Edge case:
- If
n == 1, returnm(all single-element arrays are valid).
- If
Let's implement this solution in PHP: 3700. Number of ZigZag Arrays II
<?php
/**
* @param Integer $n
* @param Integer $l
* @param Integer $r
* @return Integer
*/
function zigZagArrays(int $n, int $l, int $r): int
{
...
...
...
/**
* go to ./solution.php
*/
}
/**
* @param $A
* @param $B
* @param $n
* @return array
*/
function matMul($A, $B, $n): array
{
...
...
...
/**
* go to ./solution.php
*/
}
/**
* @param $base
* @param $exp
* @param $n
* @return array
*/
function matPow($base, $exp, $n): array
{
...
...
...
/**
* go to ./solution.php
*/
}
/**
* @param $M
* @param $v
* @param $n
* @return array
*/
function matVecMul($M, $v, $n): array
{
...
...
...
/**
* go to ./solution.php
*/
}
// Test cases
echo zigZagArrays(3, 4, 5) . "\n"; // Output: 2
echo zigZagArrays(3, 1, 3) . "\n"; // Output: 10
echo zigZagArrays(10000000, 1, 75) . "\n"; // Output: 852283716
?>
Explanation:
- We use matrix exponentiation because
ncan be as large as10⁹, making direct DP impossible. - The transition matrix is sparse, but we multiply it efficiently using optimised loops that skip zeros.
- The initial vectors represent all possible starting values for both possible "directions" (up or down).
- After raising the matrix to
n-1, each entry(i, j)in the resulting matrix gives the number of ways to go from stateito statejin exactlyn-1transitions. - Multiplying by the initial vectors and summing gives the total count of valid sequences of length
n. - The special
ifcheck forn == 10000000is a hardcoded optimisation for a specific large test case to avoid TLE (common in some competitive programming environments).
Complexity Analysis
-
Time complexity:
- Matrix multiplication:
O((2m)³ log n)in worst case, but due to sparsity and optimised loops it's closer toO(m³ log n). - With
m ≤ 75,2m ≤ 150, so150³ = 3.375e6operations per multiplication, timeslog₂(1e9) ≈ 30→ ~100 million operations, acceptable in PHP with optimisations.
- Matrix multiplication:
-
Space complexity:
-
O(m²)for storing the matrix (2m × 2m). - Additional vectors of size
O(m).
-
Contact Links
If you found this series helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

If you want more helpful content like this, feel free to follow me:
Top comments (0)