Có n điểm trên đường thẳng tại x=0..n-1. Vẽ đúng k đoạn thẳng không giao nhau (mỗi đoạn ≥ 2 điểm, đầu mút nguyên, có thể chia sẻ đầu mút). Đếm số cách, modulo 109+7.
Ví dụ: n=4, k=2 → 5 cách: [(0,2),(2,3)], [(0,1),(1,3)], [(0,1),(2,3)], [(1,2),(2,3)], [(0,1),(1,2)].
Giải thuật (DP đệ quy + Memoization)
m = 10**9+7,n = n-1(số khoảng giữa các điểm).- Hàm
dp(i, covered, j): xét khoảng i,covered= khoảng trước có đang trong đoạn,j= số đoạn đã tạo.- Nếu
i == n: trả vềj == k. - Nếu
j > k: trả về 0. ans = dp(i+1, False, j) + dp(i+1, True, j+1)(không bắt đầu đoạn / bắt đầu đoạn mới).- Nếu
covered:ans += dp(i+1, True, j)(tiếp tục đoạn hiện tại). - Trả về
ans % m.
- Nếu
- Gọi
dp(0, False, 0).
Ví dụ minh họa
def solve(n, k):
m = 10**9 + 7
n -= 1
from functools import lru_cache
@lru_cache(None)
def dp(i, covered, j):
if i == n:
return j == k
if j > k:
return 0
ans = dp(i + 1, False, j) + dp(i + 1, True, j + 1)
if covered:
ans += dp(i + 1, True, j)
return ans % m
return dp(0, False, 0)
n = 4
k = 2
print(solve(n, k))
Đầu vào
4, 2
Đầu ra
5