Problem p03152 (python)

Fixed submission:
h, w = [int(item) for item in input().split()]
total_item = h*w
MOD = 10**9 + 7
n = total_item + 10

fac = [1] + [0] * n
fac_inv = [1] + [0] * n
for i in range(1, n+1):
    fac[i] = fac[i-1] * (i) % MOD
    fac_inv[i] = fac_inv[i-1] * pow(i, MOD-2, MOD) % MOD

def mod_nPr(n, r):
    if n == 0 and r == 0:
        return 1
    if n < r or n < 0:
        return 0
    return fac[n] * fac_inv[n-r] % MOD

row_lim = [int(item) for item in input().split()] + [10**9]
col_lim = [int(item) for item in input().split()] + [10**9]
row_lim.sort()
col_lim.sort()

# Checked identity
for i in range(h):
    if row_lim[i] == row_lim[i+1]:
        print(0); exit()
for i in range(w):
    if col_lim[i] == col_lim[i+1]:
        print(0); exit()

citr = 0; ritr =0

ans = 1
itr = 0
available = total_item 
axis_num = h + w
while itr < axis_num:
    rlim = row_lim[ritr]
    clim = col_lim[citr]
    if rlim < clim:
        to_use = available - (total_item - rlim)
        if to_use < w:
            print(0); exit()
        ans *= (mod_nPr(to_use, w) - mod_nPr(to_use-1, w) + MOD)
        available -= w
        ritr += 1
        h -= 1
        itr += 1
    elif clim < rlim:
        to_use = available - (total_item - clim)
        if to_use < h:
            print(0); exit()
        ans *= (mod_nPr(to_use, h) - mod_nPr(to_use-1, h) + MOD)
        available -= h
        citr += 1
        w -= 1
        itr += 1
    else:
        to_use = available - (total_item - clim)
        if to_use < h + w - 1:
            print(0); exit()
        ans *= mod_nPr(to_use - 1, h + w - 2)
        available -= h + w - 1
        citr += 1; ritr += 1
        w -= 1; h -= 1
        itr += 2
    ans %= MOD
print(ans)

Buggy submission (verdict: Runtime Error):
from collections import Counter
MOD = 10**9 + 7
n = 10**4

fac = [1] + [0] * n
fac_inv = [1] + [0] * n
for i in range(1, n+1):
    fac[i] = fac[i-1] * (i) % MOD
    fac_inv[i] = fac_inv[i-1] * pow(i, MOD-2, MOD) % MOD

def mod_nPr(n, r):
    if n == 0 and r == 0:
        return 1
    if n < r or n < 0:
        return 0
    return fac[n] * fac_inv[n-r] % MOD

h, w = [int(item) for item in input().split()]
total_item = h*w
row_lim = [int(item) for item in input().split()] + [10**9]
col_lim = [int(item) for item in input().split()] + [10**9]
row_lim.sort()
col_lim.sort()

# Checked identity
for i in range(h):
    if row_lim[i] == row_lim[i+1]:
        print(0); exit()
for i in range(w):
    if col_lim[i] == col_lim[i+1]:
        print(0); exit()

citr = 0; ritr =0

ans = 1
itr = 0
available = total_item 
axis_num = h + w
while itr < axis_num:
    rlim = row_lim[ritr]
    clim = col_lim[citr]
    if rlim < clim:
        to_use = available - (total_item - rlim)
        if to_use < w:
            print(0); exit()
        ans *= (mod_nPr(to_use, w) - mod_nPr(to_use-1, w) + MOD)
        available -= w
        ritr += 1
        h -= 1
        itr += 1
    elif clim < rlim:
        to_use = available - (total_item - clim)
        if to_use < h:
            print(0); exit()
        ans *= (mod_nPr(to_use, h) - mod_nPr(to_use-1, h) + MOD)
        available -= h
        citr += 1
        w -= 1
        itr += 1
    else:
        to_use = available - (total_item - clim)
        if to_use < h + w - 1:
            print(0); exit()
        ans *= mod_nPr(to_use - 1, h + w - 2)
        available -= h + w - 1
        citr += 1; ritr += 1
        w -= 1; h -= 1
        itr += 2
    ans %= MOD
print(ans)