Number of ZigZag Arrays I

hard dynamic programming prefix sum counting

Problem

Given integers n, l, r, count the length-n arrays whose every element is in [l, r], where no two adjacent elements are equal and no three consecutive elements are strictly increasing or strictly decreasing. In other words, the array must strictly alternate up, down, up, down… (a zigzag). Return the count modulo 109 + 7.

Inputn = 3, l = 4, r = 5
Output2
Only [4, 5, 4] and [5, 4, 5] zigzag within values {4, 5}.

def zigZagArrays(n, l, r):
    MOD = 10**9 + 7
    m = r - l + 1                       # number of distinct values
    up = [1] * m                        # ends at x, next move must be UP
    down = [1] * m                      # ends at x, next move must be DOWN
    for _ in range(n - 1):              # extend the array one cell at a time
        new_up = [0] * m
        new_down = [0] * m
        prefix = 0                      # running sum of up[0..y-1]
        for y in range(m):              # append y going UP  (x < y, from up)
            new_down[y] = prefix        # next move flips to DOWN
            prefix = (prefix + up[y]) % MOD
        suffix = 0                      # running sum of down[y+1..]
        for y in range(m - 1, -1, -1):  # append y going DOWN (x > y, from down)
            new_up[y] = suffix          # next move flips to UP
            suffix = (suffix + down[y]) % MOD
        up, down = new_up, new_down
    return (sum(up) + sum(down)) % MOD  # last move was down + last move was up
function zigZagArrays(n, l, r) {
  const MOD = 1000000007n;
  const m = r - l + 1;                       // number of distinct values
  let up = new Array(m).fill(1n);            // ends at x, next move must be UP
  let down = new Array(m).fill(1n);          // ends at x, next move must be DOWN
  for (let step = 0; step < n - 1; step++) { // extend the array one cell
    const nu = new Array(m).fill(0n), nd = new Array(m).fill(0n);
    let prefix = 0n;                          // running sum of up[0..y-1]
    for (let y = 0; y < m; y++) {             // append y going UP (x < y)
      nd[y] = prefix;                          // next move flips to DOWN
      prefix = (prefix + up[y]) % MOD;
    }
    let suffix = 0n;                          // running sum of down[y+1..]
    for (let y = m - 1; y >= 0; y--) {        // append y going DOWN (x > y)
      nu[y] = suffix;                          // next move flips to UP
      suffix = (suffix + down[y]) % MOD;
    }
    up = nu; down = nd;
  }
  let ans = 0n;
  for (let y = 0; y < m; y++) ans = (ans + up[y] + down[y]) % MOD;
  return Number(ans);
}
int zigZagArrays(int n, int l, int r) {
    final long MOD = 1_000_000_007L;
    int m = r - l + 1;                         // number of distinct values
    long[] up = new long[m], down = new long[m];
    java.util.Arrays.fill(up, 1L);             // next move must be UP
    java.util.Arrays.fill(down, 1L);           // next move must be DOWN
    for (int step = 0; step < n - 1; step++) { // extend the array one cell
        long[] nu = new long[m], nd = new long[m];
        long prefix = 0;                       // running sum of up[0..y-1]
        for (int y = 0; y < m; y++) {          // append y going UP (x < y)
            nd[y] = prefix;                    // next move flips to DOWN
            prefix = (prefix + up[y]) % MOD;
        }
        long suffix = 0;                       // running sum of down[y+1..]
        for (int y = m - 1; y >= 0; y--) {     // append y going DOWN (x > y)
            nu[y] = suffix;                    // next move flips to UP
            suffix = (suffix + down[y]) % MOD;
        }
        up = nu; down = nd;
    }
    long ans = 0;
    for (int y = 0; y < m; y++) ans = (ans + up[y] + down[y]) % MOD;
    return (int) ans;
}
int zigZagArrays(int n, int l, int r) {
    const long long MOD = 1000000007LL;
    int m = r - l + 1;                          // number of distinct values
    vector<long long> up(m, 1), down(m, 1);     // next move UP / next move DOWN
    for (int step = 0; step < n - 1; step++) {  // extend the array one cell
        vector<long long> nu(m, 0), nd(m, 0);
        long long prefix = 0;                   // running sum of up[0..y-1]
        for (int y = 0; y < m; y++) {           // append y going UP (x < y)
            nd[y] = prefix;                     // next move flips to DOWN
            prefix = (prefix + up[y]) % MOD;
        }
        long long suffix = 0;                   // running sum of down[y+1..]
        for (int y = m - 1; y >= 0; y--) {      // append y going DOWN (x > y)
            nu[y] = suffix;                     // next move flips to UP
            suffix = (suffix + down[y]) % MOD;
        }
        up = nu; down = nd;
    }
    long long ans = 0;
    for (int y = 0; y < m; y++) ans = (ans + up[y] + down[y]) % MOD;
    return (int) ans;
}
Time: O(n · m), m = r − l + 1 Space: O(m)