public class Euler690 {
    static final long MOD = 1000000007L;

    static long powMod(long base, long exp) {
        long out = 1;
        base %= MOD;
        while (exp > 0) {
            if ((exp & 1) != 0)
                out = (out * base) % MOD;
            base = (base * base) % MOD;
            exp >>= 1;
        }
        return out;
    }

    static long[] precomputeInverses(int n) {
        long[] inv = new long[n + 1];
        if (n >= 1)
            inv[1] = 1;
        for (int i = 2; i <= n; ++i) {
            long quotient = MOD / i;
            long remainder = MOD % i;
            inv[i] = (MOD - (quotient * inv[(int) remainder]) % MOD) % MOD;
        }
        return inv;
    }

    static long[] convolveTruncated(long[] a, long[] b, int n) {
        long[] out = new long[n + 1];
        int maxI = Math.min(n, a.length - 1);
        int maxJTotal = Math.min(n, b.length - 1);

        for (int i = 0; i <= maxI; ++i) {
            long ai = a[i];
            if (ai == 0)
                continue;
            int maxJ = Math.min(maxJTotal, n - i);
            for (int j = 0; j <= maxJ; ++j) {
                long bj = b[j];
                if (bj == 0)
                    continue;
                out[i + j] = (out[i + j] + ai * bj) % MOD;
            }
        }
        return out;
    }

    static long[] invertSeries(long[] den, int n) {
        long[] out = new long[n + 1];
        out[0] = powMod(den[0], MOD - 2);
        for (int i = 1; i <= n; ++i) {
            long sum = 0;
            for (int k = 1; k <= i; ++k) {
                sum = (sum + den[k] * out[i - k]) % MOD;
            }
            out[i] = (MOD - (out[0] * sum) % MOD) % MOD;
        }
        return out;
    }

    static long[] partitionSeries(int n) {
        long[] p = new long[n + 1];
        p[0] = 1;
        for (int part = 1; part <= n; ++part) {
            for (int i = part; i <= n; ++i) {
                p[i] = (p[i] + p[i - part]) % MOD;
            }
        }
        return p;
    }

    static long[] computeLobsterTreeCounts(int n, long[] inv) {
        long[] p = partitionSeries(n);

        long[] inv1mx = new long[n + 1];
        for (int i = 0; i <= n; i++)
            inv1mx[i] = 1;

        long[] a = new long[n + 1];
        for (int i = 0; i <= n; ++i) {
            a[i] = (p[i] - inv1mx[i] + MOD) % MOD;
        }

        long[] xP = new long[n + 1];
        for (int i = 1; i <= n; ++i) {
            xP[i] = p[i - 1];
        }

        long[] den1 = new long[n + 1];
        den1[0] = 1;
        for (int i = 1; i <= n; ++i) {
            den1[i] = (MOD - xP[i]) % MOD;
        }
        long[] invDen1 = invertSeries(den1, n);

        long[] aSq = convolveTruncated(a, a, n);
        long[] part1 = convolveTruncated(aSq, invDen1, n);

        long[] p2 = new long[n + 1];
        for (int i = 0; i <= n; i += 2) {
            p2[i] = p[i / 2];
        }

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

        long[] b = new long[n + 1];
        for (int i = 0; i <= n; ++i) {
            b[i] = (p2[i] - inv1mx2[i] + MOD) % MOD;
        }

        long[] onePlusXP = xP.clone();
        onePlusXP[0] = (onePlusXP[0] + 1) % MOD;

        long[] den2 = new long[n + 1];
        den2[0] = 1;
        for (int i = 2; i <= n; ++i) {
            den2[i] = (MOD - p2[i - 2]) % MOD;
        }
        long[] invDen2 = invertSeries(den2, n);

        long[] tmp = convolveTruncated(b, onePlusXP, n);
        long[] part2 = convolveTruncated(tmp, invDen2, n);

        long[] lobsters = new long[n + 1];
        for (int i = 0; i + 2 <= n; ++i) {
            long sum = (part1[i] + part2[i]) % MOD;
            lobsters[i + 2] = (lobsters[i + 2] + sum * inv[2]) % MOD;
        }

        for (int i = 1; i <= n; ++i) {
            lobsters[i] = (lobsters[i] + xP[i]) % MOD;
        }

        long[] rec = new long[n + 1];
        rec[0] = 1;
        for (int i = 1; i <= n; ++i) {
            long v = rec[i - 1];
            if (i >= 2)
                v = (v + rec[i - 2]) % MOD;
            if (i >= 3)
                v = (v - rec[i - 3] + MOD) % MOD;
            rec[i] = v;
        }

        for (int i = 0; i + 3 <= n; ++i) {
            lobsters[i + 3] = (lobsters[i + 3] - rec[i] + MOD) % MOD;
        }

        return lobsters;
    }

    static long[] eulerTransform(long[] treeCounts, int n, long[] inv) {
        long[] c = new long[n + 1];
        for (int d = 1; d <= n; ++d) {
            long val = (d * treeCounts[d]) % MOD;
            for (int m = d; m <= n; m += d) {
                c[m] = (c[m] + val) % MOD;
            }
        }

        long[] out = new long[n + 1];
        out[0] = 1;

        for (int i = 1; i <= n; ++i) {
            long sum = 0;
            for (int k = 1; k <= i; ++k) {
                sum = (sum + c[k] * out[i - k]) % MOD;
            }
            out[i] = (sum * inv[i]) % MOD;
        }

        return out;
    }

    public static String solve() {
        int n = 2019;
        long[] inv = precomputeInverses(n);
        long[] lobsters = computeLobsterTreeCounts(n, inv);
        long[] tom = eulerTransform(lobsters, n, inv);
        return Long.toString(tom[n]);
    }

    public static void main(String[] args) {
        System.out.println(solve());
    }
}
