Problem:
Score : 800 points

Problem Statement

Snuke has a string x of length N.
Initially, every character in x is 0.

Snuke can do the following two operations any number of times in any order:

Choose A consecutive characters in x and replace each of them with 0.

Choose B consecutive characters in x and replace each of them with 1.

Find the number of different strings that x can be after Snuke finishes doing operations.
This count can be enormous, so compute it modulo (10^9+7).

Constraints

1 \leq N \leq 5000

1 \leq A,B \leq N

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N A B

Output

Print the number of different strings that x can be after Snuke finishes doing operations, modulo (10^9+7).

Sample Input 1

4 2 3

Sample Output 1

11

For example, x can be 0011 or 1111 in the end, but cannot be 0110.

Sample Input 2

10 7 2

Sample Output 2

533

Sample Input 3

1000 100 10

Sample Output 3

828178524

Solution in Kotlin (1.3.71) (judge verdict: Accepted)

import kotlin.math.max

const val MOD = 1000000007L

fun main() {
    var (n, a, b) = readLine()!!.split(" ").map { it.toInt() }
    if (b < a) {
        val c = b
        b = a
        a = c
    }
    val pow2 = LongArray(n + 1)
    pow2[0] = 1L
    for (j in 1..n) {
        pow2[j] = (2L * pow2[j - 1]) % MOD
    }
    if (a == 1) {
        println(pow2[n])
    } else {
        val dp = Array(n + 1) { LongArray(b + 1) }
        val dpOverall = LongArray(n + 1)
        dp[0][0] = 1L
        dpOverall[0] = 1L
        var answer = pow2[n - b]
        //println("\tanswer = $answer")
        for (j in 1..n) {
            for (k in 1..b) {
                dp[j][k] = when (k) {
                    1 -> if (j == 1) 1L else {
                        var res = 0L
                        for (j2 in max(0, j - a) until j - 1) {
                            res += dpOverall[j2]
                        }
                        res
                    }
                    2 -> dp[j - 1][1]
                    else -> (2L * dp[j - 1][k - 1]) - (if (j >= 2 && k >= 2) dp[j - 2][k - 2] else 0L) + (if (j >= a + 1 && k >= a + 1) dp[j - 1 - a][k - 1 - a] else 0L)
                }
                dp[j][k] %= MOD
                if (k != b) {
                    dpOverall[j] += dp[j][k]
                }
                //println("dp[$j][$k] = ${dp[j][k]}")
                if (k == b) {
                    answer += pow2[n - j] * dp[j][b]
                    answer %= MOD
                } else if (j + max(a, b - k) <= n) {
                    answer += pow2[n - (j + max(a, b - k))] * dp[j][k]
                    answer %= MOD
                }
                //println("\tanswer = $answer")
            }
            dpOverall[j] %= MOD
        }
        answer += MOD
        answer %= MOD
        println(answer)
    }
}