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 C# (Mono-csc 3.5.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AtCoder {
    class RangeSet {
        const long MOD = 1000000007L;

        static void Main(string[] args) {
            var parts = Console.ReadLine().Split(' ');
            int N = int.Parse(parts[0]);
            int A = int.Parse(parts[1]);
            int B = int.Parse(parts[2]);
            if (A>B) {
                int tmp = A;
                A = B;
                B = tmp;
            }

            long ans = 1;
            for (int i = 0; i < N; i++) {
                ans = (2 * ans) % MOD;
            }

            long[][] dp1 = new long[N + 1][];
            for (int i = 0; i <= N; i++) {
                dp1[i] = new long[2];
            }

            dp1[1][1] = 1;
            for (int len = 1; len < N; len++) {
                dp1[len + 1][1] += dp1[len][0] + dp1[len][1];
                dp1[len + 1][1] %= MOD;

                for (int zLen = A; len + zLen <= N; zLen++) {
                    dp1[len + zLen][0] += dp1[len][1];
                    dp1[len + zLen][0] %= MOD;
                }
            }

            long[][] dp2 = new long[N + 1][];
            for (int i = 0; i <= N; i++) {
                dp2[i] = new long[2];
            }

            dp2[0][0] = 1;
            dp2[0][1] = 1;
            for (int oLen = 1; oLen < B; oLen++) {
                dp2[oLen][1] = dp1[oLen][0];
            }

            for (int len = 0; len < N; len++) {
                for (int zLen = 1; zLen < A && len + zLen <= N; zLen++) {
                    dp2[len + zLen][0] += dp2[len][1];
                    dp2[len + zLen][0] %= MOD;
                }
                for (int oLen = 1; oLen < B && len + oLen <= N; oLen++) {
                    dp2[len + oLen][1] += dp2[len][0] * dp1[oLen][1];
                    dp2[len + oLen][1] %= MOD;

                    if (len + oLen == N) {
                        dp2[len + oLen][1] += dp2[len][0] * dp1[oLen][0];
                        dp2[len + oLen][1] %= MOD;
                    }
                }
            }

            ans -= dp2[N][0] + dp2[N][1];
            ans = (ans + 2 * MOD) % MOD;
            Console.WriteLine(ans);
        }
    }
}