Recursive functions can be used to solve problems by breaking them down into smaller subproblems. Dynamic programming is a technique for solving recursive problems more efficiently by avoiding recomputing results. It works by either building up the solution from smallest to largest subproblems (bottom-up) or saving computed results to lookup later (top-down). Examples where dynamic programming improves performance include calculating factorials, Fibonacci numbers, binomial coefficients, and the Poisson-binomial distribution.