import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Solution {

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;

		st = new StringTokenizer(br.readLine());

		long n = Long.parseLong(st.nextToken());
		int m = Integer.parseInt(st.nextToken());

		long[][] a = new long[m][m];
		a[0][0] = 1l;
		a[0][m - 1] = 1l;

		for (int i = 1; i < a.length; i++) {
			a[i][i - 1] = 1l;
		}

		long[][] ans = pow(a, n + 1);
		System.out.println(ans[0][m - 1]);
		// print();
	}

	static void print(long[][] a) {
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a.length; j++) {
				System.out.print(a[i][j] + " ");
			}
			System.out.println();
		}
	}

	static long[][] pow(long[][] a, long n) {
		if (n == 1) {
			return a;
		}

		if (n % 2 == 0) {
			long[][] tmp = pow(a, n / 2);
			return multiply(tmp, tmp);
		} else {
			long[][] tmp = pow(a, n / 2);
			return multiply(multiply(tmp, tmp), a);
		}
	}

	static int MOD = 1000000007;

	static long[][] multiply(long[][] a, long[][] b) {
		int n = a.length;
		long[][] ans = new long[n][n];

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				long sum = 0l;
				for (int k = 0; k < n; k++) {
					long temp = (a[i][k] * b[k][j]) % MOD;
					sum = (sum + temp) % MOD;
				}
				ans[i][j] = sum;
			}
		}

		return ans;
	}

}

// package Practice.CF1117;

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class CF1117D {
    static FastReader s;
    static PrintWriter out;
    static String INPUT = "1 3\n";
    static int mod = 1000_000_007;
    static long[][] I;

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
        out = new PrintWriter(System.out);
        s = new FastReader(oj);
        long n = s.nextLong();
        int m = s.nextInt();
        long[][] arr = new long[m][m];
        I = new long[m][m];
        arr[m - 1][0] = 1L;
        arr[m - 1][m - 1] = 1L;
        for (int i = 0; i < m - 1; i++) {
            arr[i][i + 1] = 1L;
            I[i][i] = 1L;
        }
        I[m - 1][m - 1] = 1L;
        long[][] fArr = new long[m][1];
        for (int i = 0; i < m; i++) {
            fArr[i][0] = 1L;
        }

        long[][] ans = mult(exp(arr, n - m + 1), fArr);
        out.println(ans[ans.length - 1][ans[0].length - 1] % mod);

//        out.println((ans.add(BigInteger.ONE)).mod(BigInteger.valueOf(mod)));
        if (!oj) {
            System.out.println(Arrays.deepToString(new Object[]{System.currentTimeMillis() - time + " ms"}));
        }
        out.flush();
    }

    public static long[][] exp(long[][] M, long n)
    {
        if (n <= 0) return I;
        if (n == 1) return M;
        long[][] res = exp(M, n/2);
        res = mult(res, res);
        if (n %2 == 0) return res;
        return mult(res, M);
    }

    public static long[][] mult(long[][] p, long[][] q) {
        long[][] r = new long[p.length][q[0].length];
        for (int i = 0; i < p.length; i++)
            for (int j = 0; j < q[0].length; j++)
                for (int k = 0; k < q.length; k++) {
                    r[i][j] += p[i][k]*q[k][j];
                    r[i][j] %= mod;
                }
        return r;
    }

    private static class Maths {
        static ArrayList<Long> printDivisors(long n) {
            // Note that this loop runs till square root
            ArrayList<Long> list = new ArrayList<>();
            for (long i = 1; i <= Math.sqrt(n); i++) {
                if (n % i == 0) {
                    if (n / i == i) {
                        list.add(i);
                    } else {
                        list.add(i);
                        list.add(n / i);
                    }
                }
            }
            return list;
        }

        //    GCD - Using Euclid theorem.
        private static long gcd(long a, long b) {
            if (b == 0) {
                return a;
            }

            return gcd(b, a % b);
        }

        //    Extended euclidean algorithm
//    Used to solve equations of the form ax + by = gcd(a,b)
//    return array [d, a, b] such that d = gcd(p, q), ap + bq = d
        static long[] extendedEuclidean(long p, long q) {
            if (q == 0)
                return new long[]{p, 1, 0};

            long[] vals = extendedEuclidean(q, p % q);
            long d = vals[0];
            long a = vals[2];
            long b = vals[1] - (p / q) * vals[2];
            return new long[]{d, a, b};
        }

        // X ^ y mod p
        static long power(long x, long y, long p) {
            long res = 1;
            x = x % p;

            while (y > 0) {
                if ((y & 1) == 1)
                    res = (res * x) % p;
                y = y >> 1;
                x = (x * x) % p;
            }
            return res;
        }

        // Returns modulo inverse of a
        // with respect to m using extended
        // Euclid Algorithm. Refer below post for details:
        // https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/
        static long inv(long a, long m) {
            long m0 = m, t, q;
            long x0 = 0, x1 = 1;

            if (m == 1)
                return 0;

            // Apply extended Euclid Algorithm
            while (a > 1) {
                q = a / m;
                t = m;
                m = a % m;
                a = t;
                t = x0;
                x0 = x1 - q * x0;
                x1 = t;
            }

            // Make x1 positive
            if (x1 < 0)
                x1 += m0;

            return x1;
        }

        // k is size of num[] and rem[].
        // Returns the smallest number
        // x such that:
        // x % num[0] = rem[0],
        // x % num[1] = rem[1],
        // ..................
        // x % num[k-2] = rem[k-1]
        // Assumption: Numbers in num[] are pairwise
        // coprime (gcd for every pair is 1)
        static long findMinX(long num[], long rem[], long k) {
            int prod = 1;
            for (int i = 0; i < k; i++)
                prod *= num[i];

            int result = 0;
            for (int i = 0; i < k; i++) {
                long pp = prod / num[i];
                result += rem[i] * inv(pp, num[i]) * pp;
            }

            return result % prod;
        }
    }

    private static class BS {
        //  Binary search
        private static int binarySearch(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    return mid;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return -1;
        }

        //    First occurence using binary search
        private static int binarySearchFirstOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    high = mid - 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }

        //    Last occurenece using binary search
        private static int binarySearchLastOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    low = mid + 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }
    }

    private static class arrays {
        // Merge sort
        static void merge(int arr[], int l, int m, int r) {
            int n1 = m - l + 1;
            int n2 = r - m;
            int L[] = new int[n1];
            int R[] = new int[n2];
            for (int i = 0; i < n1; ++i)
                L[i] = arr[l + i];
            for (int j = 0; j < n2; ++j)
                R[j] = arr[m + 1 + j];
            int i = 0, j = 0;
            int k = l;
            while (i < n1 && j < n2) {
                if (L[i] <= R[j]) {
                    arr[k] = L[i];
                    i++;
                } else {
                    arr[k] = R[j];
                    j++;
                }
                k++;
            }

            while (i < n1) {
                arr[k] = L[i];
                i++;
                k++;
            }

            while (j < n2) {
                arr[k] = R[j];
                j++;
                k++;
            }
        }

        static void sort(int arr[], int l, int r) {
            if (l < r) {
                int m = (l + r) / 2;
                sort(arr, l, m);
                sort(arr, m + 1, r);
                merge(arr, l, m, r);
            }
        }

        static void sort(int[] arr) {
            sort(arr, 0, arr.length - 1);
        }
    }

    private static class UnionFindDisjointSet {
        int[] parent;
        int[] size;
        int n;
        int size1;

        public UnionFindDisjointSet(int n) {
            this.n = n;
            this.parent = new int[n];
            this.size = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }

            for (int i = 0; i < n; i++) {
                size[i] = 1;
            }

            this.size1 = n;
        }

        private int numDisjointSets() {
            System.out.println(size1);
            return size1;
        }

        private boolean find(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return true;
            }
            return false;
        }

        private int root(int b) {
            while (parent[b] != b) {
                parent[b] = parent[parent[b]];
                b = parent[b];
            }
            return b;
        }

        private void union(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return;
            }

            if (size[rootA] < size[rootB]) {
                parent[rootA] = parent[rootB];
                size[rootB] += size[rootA];
            } else {
                parent[rootB] = parent[rootA];
                size[rootA] += size[rootB];
            }
            size1--;
            System.out.println(Arrays.toString(parent));
        }
    }

    private static class SegTree {
        int[] st;
        int[] arr;

        public SegTree(int[] arr) {
            this.arr = arr;
            int size = (int) Math.ceil(Math.log(arr.length) / Math.log(2));
            st = new int[(int) ((2 * Math.pow(2, size)) - 1)];
            buildSegmentTree(1, 0, arr.length - 1);
        }

        //**********JUST CALL THE CONSTRUCTOR, THIS FUNCTION WILL BE CALLED AUTOMATICALLY******
        private void buildSegmentTree(int index, int L, int R) {
            if (L == R) {
                st[index] = arr[L];
                return;
            }

            buildSegmentTree(index * 2, L, (L + R) / 2);
            buildSegmentTree(index * 2 + 1, (L + R) / 2 + 1, R);
//          Replace this line if you want to change the function of the Segment tree.
            st[index] = Math.min(st[index * 2], st[index * 2 + 1]);
        }

        //***********We have to use this function **************
        private int Query(int queL, int queR) {
            return Query1(1, 0, arr.length - 1, queL, queR);
        }

        //This is a helper function.
        //************* DO NOT USE THIS ****************
        private int Query1(int index, int segL, int segR, int queL, int queR) {
            if (queL > segR || queR < segL) {
                return -1;
            }

            if (queL <= segL && queR >= segR) {
                return st[index];
            }

            int ans1 = Query1(index * 2, segL, (segL + segR) / 2, queL, queR);
            int ans2 = Query1(index * 2 + 1, (segL + segR) / 2 + 1, segR, queL, queR);
            if (ans1 == -1) {
                return ans2;
            }

            if (ans2 == -1) {
                return ans1;
            }
//             Segment tree implemented for range minimum query. Change the below line to change the function.
            return Math.min(ans1, ans2);
        }

        private void update(int idx, int val) {
            update1(1, 0, arr.length - 1, idx, val);
        }

        private void update1(int node, int queL, int queR, int idx, int val) {
            // idx - index to be updated in the array
            // node - index to be updated in the seg tree
            if (queL == queR) {
                // Leaf node
                arr[idx] += val;
                st[node] += val;
            } else {
                int mid = (queL + queR) / 2;
                if (queL <= idx && idx <= mid) {
                    // If idx is in the left child, recurse on the left child
                    update1(2 * node, queL, mid, idx, val);
                } else {
                    // if idx is in the right child, recurse on the right child
                    update1(2 * node + 1, mid + 1, queR, idx, val);
                }
                // Internal node will have the min of both of its children
                st[node] = Math.min(st[2 * node], st[2 * node + 1]);
            }
        }

    }

    private static class FastReader {
        InputStream is;

        public FastReader(boolean onlineJudge) {
            is = onlineJudge ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        }

        byte[] inbuf = new byte[1024];
        public int lenbuf = 0, ptrbuf = 0;

        int readByte() {
            if (lenbuf == -1)
                throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0)
                    return -1;
            }
            return inbuf[ptrbuf++];
        }

        boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b))
                ;
            return b;
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        char nextChar() {
            return (char) skip();
        }

        String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        String nextLine() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while ((!isSpaceChar(b) || b == ' ')) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        char[][] nextMatrix(int n, int m) {
            char[][] map = new char[n][];
            for (int i = 0; i < n; i++)
                map[i] = next(m);
            return map;
        }

        int[] nextIntArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        long[] nextLongArray(int n) {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
                a[i] = nextLong();
            return a;
        }

        int[][] next2DInt(int n, int m) {
            int[][] arr = new int[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextIntArray(m);
            }
            return arr;
        }

        long[][] next2DLong(int n, int m) {
            long[][] arr = new long[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLongArray(m);
            }
            return arr;
        }

        int[] shuffle(int[] arr) {
            Random r = new Random();
            for (int i = 1, j; i < arr.length; i++) {
                j = r.nextInt(i);
                arr[i] = arr[i] ^ arr[j];
                arr[j] = arr[i] ^ arr[j];
                arr[i] = arr[i] ^ arr[j];
            }
            return arr;
        }

        int[] uniq(int[] arr) {
            Arrays.sort(arr);
            int[] rv = new int[arr.length];
            int pos = 0;
            rv[pos++] = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if (arr[i] != arr[i - 1]) {
                    rv[pos++] = arr[i];
                }
            }
            return Arrays.copyOf(rv, pos);
        }
    }

}

import java.io.*;
import java.util.StringTokenizer;

public class Solution {
    static final int INF = (int) 1e9;
    static final int mod = (int) (1e9 + 7);

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);
        long n = sc.nextLong();
        int m = sc.nextInt();
        int[][] base = new int[m][m];
        base[0][0] = 1;
        base[0][m - 1] = 1;
        for (int i = 1; i < m; i++)
            base[i][i - 1] = 1;
        int[][] base2 = new int[m][1];
        for (int i = m - 1; i >= 0; i--)
            base2[i][0] = 1;
        int[][] ans = matMul(matPow(base, n - m + 1), base2, m, m, 1);
        ans[0][0] = (ans[0][0] + mod) % mod;
        out.println(ans[0][0]);
        out.flush();
        out.close();
    }

    static int[][] matMul(int[][] A, int[][] B, int p, int q, int r)    //C(p x r) = A(p x q) x (q x r) -- O(p x q x r)
    {
        int[][] C = new int[p][r];
        for (int i = 0; i < p; ++i)
            for (int j = 0; j < r; ++j)
                for (int k = 0; k < q; ++k)
                    C[i][j] = (int) ((C[i][j] + 1l * A[i][k] * B[k][j]) % mod);
        return C;
    }

    static int[][] matPow(int[][] base, long p) {
        int n = base.length;
        int[][] ans = new int[n][n];
        for (int i = 0; i < n; i++)
            ans[i][i] = 1;
        while (p > 0) {
            if ((p & 1) == 1)
                ans = matMul(ans, base, n, n, n);
            base = matMul(base, base, n, n, n);
            p >>= 1;
        }

        return ans;
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(InputStream system) {
            br = new BufferedReader(new InputStreamReader(system));
        }

        public Scanner(String file) throws Exception {
            br = new BufferedReader(new FileReader(file));
        }

        public String next() throws IOException {
            while (st == null || !st.hasMoreTokens()) st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public String nextLine() throws IOException {
            return br.readLine();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        public char nextChar() throws IOException {
            return next().charAt(0);
        }

        public Long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public boolean ready() throws IOException {
            return br.ready();
        }

        public void waitForInput() throws InterruptedException {
            Thread.sleep(3000);
        }

        public int[] nextIntArray(int n) throws IOException {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        public Integer[] nextIntegerArray(int n) throws IOException {
            Integer[] a = new Integer[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        public double[] nextDoubleArray(int n) throws IOException {
            double[] ans = new double[n];
            for (int i = 0; i < n; i++)
                ans[i] = nextDouble();
            return ans;
        }

    }
}

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.*;
import java.util.*;
import java.util.LinkedList;
import java.math.*;
import java.lang.*;
import java.util.PriorityQueue;
import static java.lang.Math.*;
@SuppressWarnings("unchecked")
public class Solution implements Runnable {
    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private SpaceCharFilter filter;
        private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars==-1)
                throw new InputMismatchException();

            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                }
                catch (IOException e) {
                    throw new InputMismatchException();
                }

                if(numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
        public int nextInt() {
            int c = read();

            while(isSpaceChar(c))
                c = read();

            int sgn = 1;

            if (c == '-') {
                sgn = -1;
                c = read();
            }

            int res = 0;
            do {
                if(c<'0'||c>'9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            while (!isSpaceChar(c));

            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;

            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            while (!isSpaceChar(c));
                return res * sgn;
        }

        public double nextDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, nextInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, nextInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }

        public String readString() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            }
            while (!isSpaceChar(c));

            return res.toString();
        }

        public boolean isSpaceChar(int c) {
            if (filter != null)
                return filter.isSpaceChar(c);
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public String next() {
            return readString();
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);
        }
    }
    public static long min(long a,long b)
    {
        if(a>b)
        {
            return b;
        }
        return a;
    }
    public static int min(int a,int b)
    {
        if(a>b)
        {
            return b;
        }
        return a;
    }
    public static long max(long a,long b)
    {
        if(a>b)
        {
            return a;
        }
        return b;
    }
    public static int max(int a,int b)
    {
        if(a>b)
        {
            return a;
        }
        return b;
    }
    static class pair
    {
      long x;
      long y;
      pair(long x,long y)
      {
        this.x = x;
        this.y = y;
      }
    }
    public static int gcd(int a,int b)
    {
        if(a==0)
        return b;
        if(b==0)
        return a;
        while((a%=b)!=0&&(b%=a)!=0);
        return a^b;
    }
    public static long mod(long x)
    {
      if(x>0)
      {
        return x;
      }
      return -x;
    }
    static int mod = (int)1e9+7;
    static long[][] dp;
    static long[][] mat;
    static int k;
    public static long[][] mult(long[][] a,long[][] b)
    {
      int n = a.length;
      int m = b[0].length;
      long[][] res = new long[n][m];
      for(int i=0;i<n;i++)
      {
        for(int j=0;j<m;j++)
        {
          for(int k=0;k<a[0].length;k++)
          {
            res[i][j]  = (res[i][j]+a[i][k]*b[k][j])%mod;
          }
        }
      }
      return res;
    }
    public static long[][] expo(long[][] mat,long pow)
    {
      long[][] res = new long[mat.length][mat.length];
      for(int i=0;i<res.length;i++)
      {
        res[i][i] = 1;
      }
      while(pow!=0)
      {
        if((pow&1)==1)
        {
          res = mult(res,mat);
        }
        mat = mult(mat,mat);
        pow = pow>>1;
      }
      return res;
    }
    public static int random(int min,int max)
    {
      return min+(int)((max-min)*Math.random());
    }
    public static void main(String args[]) throws Exception {
        new Thread(null, new Solution(),"Main",1<<26).start();
    }    public void run() {
      InputReader sc  = new InputReader(System.in);
      PrintWriter out = new PrintWriter(System.out);
      int t1 = 1;
      while(t1-->0)
      {
        long n = sc.nextLong();
        k = sc.nextInt();
        dp = new long[k][1];
        for(int i=0;i<k;i++)
        {
          dp[i][0] = 1;
        }
        dp[k-1][0] = 2;
        if(n<=k)
        {
          out.println(dp[(int)(n-1)][0]);
          out.close();
          return;
        }
        mat = new long[k][k];
        for(int i=0;i<k-1;i++)
        {
          mat[i][i+1] = 1;
        }
        mat[k-1][0] = 1;
        mat[k-1][k-1] = 1;
        mat = expo(mat,n-k);
        dp = mult(mat,dp);
        out.println(dp[k-1][0]);
      }
      out.close();
  }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author llamaoo7
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DMagicGems solver = new DMagicGems();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems {
        int MAX = 1_000_000_007;

        long add(long a, long b) {
            return (a + b) % MAX;
        }

        long mult(long a, long b) {
            return (a * b) % MAX;
        }

        long[][] matMult(long[][] a, long[][] b) {
            long[][] res = new long[a.length][b[0].length];
            for (int i = 0; i < a.length; i++)
                for (int j = 0; j < b[0].length; j++)
                    for (int k = 0; k < a[i].length; k++)
                        res[i][j] = add(res[i][j], mult(a[i][k], b[k][j]));
            return res;
        }

        long[][] matPow(long[][] a, long n) {
            long[][] res = new long[a.length][a.length];
            for (int i = 0; i < a.length; i++) res[i][i] = 1;
            while (n > 0) {
                if (n % 2 == 1) res = matMult(res, a);
                a = matMult(a, a);
                n /= 2;
            }
            return res;
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long n = in.nextLong();
            int m = in.nextInt();
            if (m > n) {
                out.println(1);
                return;
            }

            long[][] M = new long[m][m];
            M[0][0] = 1;
            M[0][m - 1] = 1;
            for (int i = 1; i < m; i++) M[i][i - 1] = 1;

            M = matPow(M, n - m + 1);
            long ans = 0;
            for (int i = 0; i < m; i++) ans = add(ans, M[0][i]);
            out.println(ans);
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}

import java.io.*;
import java.util.*;

public class CF1117D {
	static final int MD = 1000000007;
	static void multiply(int[][] aa, int[][] bb, int[][] cc, int n) {
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++) {
				long c = 0;
				for (int k = 0; k < n; k++)
					c = (c + (long) aa[i][k] * bb[k][j]) % MD;
				cc[i][j] = (int) c;
			}
	}
	static void power(int[][] aa, int[][] pp, int[][] tt, int n, long k) {
		if (k == 0) {
			for (int i = 0; i < n; i++)
				for (int j = 0; j < n; j++)
					pp[i][j] = i == j ? 1 : 0;
			return;
		}
		if (k % 2 == 0) {
			power(aa, tt, pp, n, k / 2);
			multiply(tt, tt, pp, n);
		} else {
			power(aa, pp, tt, n, k / 2);
			multiply(pp, pp, tt, n);
			multiply(tt, aa, pp, n);
		}
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		long n = Long.parseLong(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		int[][] aa = new int[m][m];
		for (int i = 0; i < m - 1; i++)
			aa[i][i + 1] = 1;
		aa[m - 1][0] = aa[m - 1][m - 1] = 1;
		int[][] pp = new int[m][m];
		int[][] tt = new int[m][m];
		power(aa, pp, tt, m, n);
		long p = 0;
		for (int j = 0; j < m; j++)
			p = (p + pp[0][j]) % MD;
		System.out.println(p);
	}
}

import java.io.*;
import java.util.Arrays;
import java.util.StringJoiner;
import java.util.StringTokenizer;
import java.util.function.IntBinaryOperator;

public class Main {

    static long N;
    static int M;

    public static void main(String[] args) {
        FastScanner sc = new FastScanner(System.in);
        N = sc.nextLong();
        M = sc.nextInt();

        System.out.println(solve());
    }

    static int MOD = 1_000_000_007;

    static int solve() {
        // 右側に 0* or 1 をくっつけていくDPを考える
        // M=3のケース
        // f4 = f1 + f3
        // f3 = f2
        // f2 = f1
        IntMat mat = new IntMat(M, M);
        mat.set(0, 0, 1);
        mat.set(0, M-1, 1);
        for (int i = 1; i < M; i++) {
            mat.set(i, i-1, 1);
        }

        IntMat powed = IntMat.pow(mat, N, MOD);
        IntMat in = new IntMat(M, 1);
        in.set(0, 0, 1);
        IntMat out = IntMat.dot(powed, in, MOD);
        return out.get(0, 0);
    }

    static class IntMat {

        final int[][] mat;

        IntMat(int r, int c) {
            mat = new int[r][c];
        }

        IntMat(int[][] mat) {
            this.mat = mat;
        }

        IntMat(int[] vec) {
            mat = new int[vec.length][1];
            for (int i = 0; i < vec.length; i++) {
                mat[i][0] = vec[i];
            }
        }

        static IntMat pow(IntMat m, long k, int mod) {
            if( m.row() != m.col() ) throw new IllegalArgumentException("row != col : " + m.row() + " " + m.col());

            int n = m.row();
            IntMat ret = new IntMat(n, n);
            for (int i = 0; i < n; i++) {
                ret.set(i, i, 1);
            }
            if( k == 0 ) return ret; // どうだろ...

            while( k > 0 ) {
                if( (k & 1) == 1 ) {
                    ret = IntMat.dot(ret, m, mod);
                }

                m = IntMat.dot(m, m, mod);
                k = k >> 1L;
            }
            return ret;
        }

        static IntMat pow(IntMat m, long k, IntBinaryOperator mul, IntBinaryOperator add) {
            if( m.row() != m.col() ) throw new IllegalArgumentException("row != col : " + m.row() + " " + m.col());

            int n = m.row();
            IntMat ret = new IntMat(n, n);
            for (int i = 0; i < n; i++) {
                ret.set(i, i, 1);
            }
            if( k == 0 ) return ret; // どうだろ...

            while( k > 0 ) {
                if( (k & 1) == 1 ) {
                    ret = IntMat.dot(ret, m, mul, add);
                }

                m = IntMat.dot(m, m, mul, add);
                k = k >> 1L;
            }
            return ret;
        }

        static IntMat dot(IntMat a, IntMat b) {
            return dot(a, b, (i, j) -> i*j, (i, j) -> i+j);
        }

        static IntMat dot(IntMat a, IntMat b, IntBinaryOperator mul, IntBinaryOperator add) {
            int[][] ret = new int[a.row()][b.col()];

            for (int r = 0; r < a.row(); r++) {
                for (int c = 0; c < b.col(); c++) {
                    int sum = 0;
                    for (int i = 0; i < b.row(); i++) {
                        sum = add.applyAsInt(sum, mul.applyAsInt(a.get(r, i), b.get(i, c)));
                    }
                    ret[r][c] = sum;
                }
            }
            return new IntMat(ret);
        }

        static IntMat dot(IntMat a, IntMat b, int mod) {
            long m2 = (long)mod * mod;

            int ar = a.row();
            int bc = b.col();
            int br = b.row();
            int[][] ret = new int[ar][bc];

            for (int r = 0; r < ar; r++) {
                for (int c = 0; c < bc; c++) {
                    long sum = 0;
                    for (int i = 0; i < br; i++) {
                        long ab = (long)a.mat[r][i] * b.mat[i][c];
                        sum += ab;
                        if( sum >= m2 ) {
                            sum -= m2;
                        }
                    }
                    ret[r][c] = (int)(sum % mod);
                }
            }
            return new IntMat(ret);
        }

        void set(int r, int c, int n) {
            mat[r][c] = n;
        }

        int get(int r, int c) {
            try {
                return mat[r][c];
            } catch( ArrayIndexOutOfBoundsException e ) {
                throw new RuntimeException("wrong index : r=" + r + " c=" + c + " row=" + row() + " col=" + col());
            }
        }

        int row() {
            return mat.length;
        }

        int col() {
            return mat[0].length;
        }
    }

    @SuppressWarnings("unused")
    static class FastScanner {
        private BufferedReader reader;
        private StringTokenizer tokenizer;

        FastScanner(InputStream in) {
            reader = new BufferedReader(new InputStreamReader(in));
            tokenizer = null;
        }

        String next() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        String nextLine() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    return reader.readLine();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken("\n");
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        int[] nextIntArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++) a[i] = nextInt();
            return a;
        }

        int[] nextIntArray(int n, int delta) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++) a[i] = nextInt() + delta;
            return a;
        }

        long[] nextLongArray(int n) {
            long[] a = new long[n];
            for (int i = 0; i < n; i++) a[i] = nextLong();
            return a;
        }
    }

    static void writeLines(int[] as) {
        PrintWriter pw = new PrintWriter(System.out);
        for (int a : as) pw.println(a);
        pw.flush();
    }

    static void writeLines(long[] as) {
        PrintWriter pw = new PrintWriter(System.out);
        for (long a : as) pw.println(a);
        pw.flush();
    }

    static void writeSingleLine(int[] as) {
        PrintWriter pw = new PrintWriter(System.out);
        for (int i = 0; i < as.length; i++) {
            if (i != 0) pw.print(" ");
            pw.print(as[i]);
        }
        pw.println();
        pw.flush();
    }

    static int max(int... as) {
        int max = Integer.MIN_VALUE;
        for (int a : as) max = Math.max(a, max);
        return max;
    }

    static int min(int... as) {
        int min = Integer.MAX_VALUE;
        for (int a : as) min = Math.min(a, min);
        return min;
    }

    static void debug(Object... args) {
        StringJoiner j = new StringJoiner(" ");
        for (Object arg : args) {
            if (arg == null) j.add("null");
            else if (arg instanceof int[]) j.add(Arrays.toString((int[]) arg));
            else if (arg instanceof long[]) j.add(Arrays.toString((long[]) arg));
            else if (arg instanceof double[]) j.add(Arrays.toString((double[]) arg));
            else if (arg instanceof Object[]) j.add(Arrays.toString((Object[]) arg));
            else j.add(arg.toString());
        }
        System.err.println(j.toString());
    }

    static void printSingleLine(int[] array) {
        PrintWriter pw = new PrintWriter(System.out);
        for (int i = 0; i < array.length; i++) {
            if (i != 0) pw.print(" ");
            pw.print(array[i]);
        }
        pw.println();
        pw.flush();
    }

    static int lowerBound(int[] array, int value) {
        int lo = 0, hi = array.length, mid;
        while (lo < hi) {
            mid = (hi + lo) / 2;
            if (array[mid] < value) lo = mid + 1;
            else hi = mid;
        }
        return lo;
    }

    static int upperBound(int[] array, int value) {
        int lo = 0, hi = array.length, mid;
        while (lo < hi) {
            mid = (hi + lo) / 2;
            if (array[mid] <= value) lo = mid + 1;
            else hi = mid;
        }
        return lo;
    }
}

import java.io.*;
import java.util.Arrays;
import java.util.StringJoiner;
import java.util.StringTokenizer;
import java.util.function.IntBinaryOperator;

public class Main {

    static long N;
    static int M;

    public static void main(String[] args) {
        FastScanner sc = new FastScanner(System.in);
        N = sc.nextLong();
        M = sc.nextInt();

        System.out.println(solve());
    }

    static int MOD = 1_000_000_007;

    static int solve() {
        // 右側に 0* or 1 をくっつけていくDPを考える
        // M=3のケース
        // f4 = f1 + f3
        // f3 = f2
        // f2 = f1
        IntMat mat = new IntMat(M, M);
        mat.set(0, 0, 1);
        mat.set(0, M-1, 1);
        for (int i = 1; i < M; i++) {
            mat.set(i, i-1, 1);
        }

        IntMat powed = IntMat.pow(mat, N, MOD);
        IntMat in = new IntMat(M, 1);
        in.set(0, 0, 1);
        IntMat out = IntMat.dot(powed, in, MOD);
        return out.get(0, 0);
    }

    static class IntMat {

        final int[][] mat;

        IntMat(int r, int c) {
            mat = new int[r][c];
        }

        IntMat(int[][] mat) {
            this.mat = mat;
        }

        IntMat(int[] vec) {
            mat = new int[vec.length][1];
            for (int i = 0; i < vec.length; i++) {
                mat[i][0] = vec[i];
            }
        }

        static IntMat pow(IntMat m, long k, int mod) {
            if( m.row() != m.col() ) throw new IllegalArgumentException("row != col : " + m.row() + " " + m.col());

            int n = m.row();
            IntMat ret = new IntMat(n, n);
            for (int i = 0; i < n; i++) {
                ret.set(i, i, 1);
            }
            if( k == 0 ) return ret; // どうだろ...

            while( k > 0 ) {
                if( (k & 1) == 1 ) {
                    ret = IntMat.dot(ret, m, mod);
                }

                m = IntMat.dot(m, m, mod);
                k = k >> 1L;
            }
            return ret;
        }

        static IntMat pow(IntMat m, long k, IntBinaryOperator mul, IntBinaryOperator add) {
            if( m.row() != m.col() ) throw new IllegalArgumentException("row != col : " + m.row() + " " + m.col());

            int n = m.row();
            IntMat ret = new IntMat(n, n);
            for (int i = 0; i < n; i++) {
                ret.set(i, i, 1);
            }
            if( k == 0 ) return ret; // どうだろ...

            while( k > 0 ) {
                if( (k & 1) == 1 ) {
                    ret = IntMat.dot(ret, m, mul, add);
                }

                m = IntMat.dot(m, m, mul, add);
                k = k >> 1L;
            }
            return ret;
        }

        static IntMat dot(IntMat a, IntMat b) {
            return dot(a, b, (i, j) -> i*j, (i, j) -> i+j);
        }

        static IntMat dot(IntMat a, IntMat b, IntBinaryOperator mul, IntBinaryOperator add) {
            int[][] ret = new int[a.row()][b.col()];

            for (int r = 0; r < a.row(); r++) {
                for (int c = 0; c < b.col(); c++) {
                    int sum = 0;
                    for (int i = 0; i < b.row(); i++) {
                        sum = add.applyAsInt(sum, mul.applyAsInt(a.get(r, i), b.get(i, c)));
                    }
                    ret[r][c] = sum;
                }
            }
            return new IntMat(ret);
        }

        static IntMat dot(IntMat a, IntMat b, int mod) {
            long m2 = (long)mod * mod;

            int[][] ret = new int[a.row()][b.col()];

            for (int r = 0; r < a.row(); r++) {
                for (int c = 0; c < b.col(); c++) {
                    long sum = 0;
                    for (int i = 0; i < b.row(); i++) {
                        long ab = (long)a.mat[r][i] * b.mat[i][c];
                        sum += ab;
                        if( sum >= m2 ) {
                            sum -= m2;
                        }
                    }
                    sum %= mod;
                    ret[r][c] = (int)sum;
                }
            }
            return new IntMat(ret);
        }

        void set(int r, int c, int n) {
            mat[r][c] = n;
        }

        int get(int r, int c) {
            try {
                return mat[r][c];
            } catch( ArrayIndexOutOfBoundsException e ) {
                throw new RuntimeException("wrong index : r=" + r + " c=" + c + " row=" + row() + " col=" + col());
            }
        }

        int row() {
            return mat.length;
        }

        int col() {
            return mat[0].length;
        }
    }

    @SuppressWarnings("unused")
    static class FastScanner {
        private BufferedReader reader;
        private StringTokenizer tokenizer;

        FastScanner(InputStream in) {
            reader = new BufferedReader(new InputStreamReader(in));
            tokenizer = null;
        }

        String next() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        String nextLine() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    return reader.readLine();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken("\n");
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        int[] nextIntArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++) a[i] = nextInt();
            return a;
        }

        int[] nextIntArray(int n, int delta) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++) a[i] = nextInt() + delta;
            return a;
        }

        long[] nextLongArray(int n) {
            long[] a = new long[n];
            for (int i = 0; i < n; i++) a[i] = nextLong();
            return a;
        }
    }

    static void writeLines(int[] as) {
        PrintWriter pw = new PrintWriter(System.out);
        for (int a : as) pw.println(a);
        pw.flush();
    }

    static void writeLines(long[] as) {
        PrintWriter pw = new PrintWriter(System.out);
        for (long a : as) pw.println(a);
        pw.flush();
    }

    static void writeSingleLine(int[] as) {
        PrintWriter pw = new PrintWriter(System.out);
        for (int i = 0; i < as.length; i++) {
            if (i != 0) pw.print(" ");
            pw.print(as[i]);
        }
        pw.println();
        pw.flush();
    }

    static int max(int... as) {
        int max = Integer.MIN_VALUE;
        for (int a : as) max = Math.max(a, max);
        return max;
    }

    static int min(int... as) {
        int min = Integer.MAX_VALUE;
        for (int a : as) min = Math.min(a, min);
        return min;
    }

    static void debug(Object... args) {
        StringJoiner j = new StringJoiner(" ");
        for (Object arg : args) {
            if (arg == null) j.add("null");
            else if (arg instanceof int[]) j.add(Arrays.toString((int[]) arg));
            else if (arg instanceof long[]) j.add(Arrays.toString((long[]) arg));
            else if (arg instanceof double[]) j.add(Arrays.toString((double[]) arg));
            else if (arg instanceof Object[]) j.add(Arrays.toString((Object[]) arg));
            else j.add(arg.toString());
        }
        System.err.println(j.toString());
    }

    static void printSingleLine(int[] array) {
        PrintWriter pw = new PrintWriter(System.out);
        for (int i = 0; i < array.length; i++) {
            if (i != 0) pw.print(" ");
            pw.print(array[i]);
        }
        pw.println();
        pw.flush();
    }

    static int lowerBound(int[] array, int value) {
        int lo = 0, hi = array.length, mid;
        while (lo < hi) {
            mid = (hi + lo) / 2;
            if (array[mid] < value) lo = mid + 1;
            else hi = mid;
        }
        return lo;
    }

    static int upperBound(int[] array, int value) {
        int lo = 0, hi = array.length, mid;
        while (lo < hi) {
            mid = (hi + lo) / 2;
            if (array[mid] <= value) lo = mid + 1;
            else hi = mid;
        }
        return lo;
    }
}

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.PrintWriter;

public class D {

	final int mod = (int) 1e9 + 7;

	long[][] mult(long[][] a, long[][] b) {
		int n = a.length;
		int m = b[0].length;
		long[][] ans = new long[n][n];
		for(int i = 0; i < n; ++i) {
			for(int j = 0; j < m; ++j) {
				for(int k = 0; k < n; ++k) {
					ans[i][j] += a[i][k] * b[k][j];
					ans[i][j] %= mod;
				}
			}
		}
		return ans;
	}

	public void solve(JS in, PrintWriter out) {
		long n = in.nextLong();
		int m = in.nextInt();
		//f(x) = f(x - 1) + f(x - m);
		long[][] mat = new long[m][m];
		mat[0][0] = 1; mat[0][m - 1] = 1;
		for(int i = 1; i < m; ++i) mat[i][i - 1] = 1;
		long[][] v = new long[m][1];
		v[0][0] = 1; //ways to make 0 things
		while(n > 0) {
			if(n % 2 == 0) {
				n /= 2;
				mat = mult(mat, mat);
			} else {
				n--;
				v = mult(mat, v);
			}
		}
		out.println(v[0][0]);
	}

	public static void main(String[] args) {
		JS in = new JS();
		PrintWriter out = new PrintWriter(System.out);
		new D().solve(in, out);
		out.close();
	}

	static class JS {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public JS() {
			in = new BufferedInputStream(System.in, BS);
		}

		public JS(String s) throws FileNotFoundException {
			in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}
	}
}

import java.io.*;
import java.util.*;
import java.util.function.BinaryOperator;

public class Main {
    private final static long mod = 1000000007;

    private final static int MAXN = 1000001;

    private static long power(long x, long y, long m) {
        long temp;
        if (y == 0)
            return 1;
        temp = power(x, y / 2, m);
        temp = (temp * temp) % m;
        if (y % 2 == 0)
            return temp;
        else
            return ((x % m) * temp) % m;
    }

    private static long power(long x, long y) {
        return power(x, y, mod);
    }

    private static long gcd(long a, long b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

    static int nextPowerOf2(int a) {
        return 1 << nextLog2(a);
    }

    static int nextLog2(int a) {
        return (a == 0 ? 0 : 32 - Integer.numberOfLeadingZeros(a - 1));
    }

    private static long modInverse(long a, long m) {
        long m0 = m;
        long y = 0, x = 1;
        if (m == 1)
            return 0;
        while (a > 1) {
            long q = a / m;
            long t = m;
            m = a % m;
            a = t;
            t = y;
            y = x - q * y;
            x = t;
        }
        if (x < 0)
            x += m0;
        return x;
    }

    private static int[] getLogArr(int n) {
        int arr[] = new int[n + 1];
        for (int i = 1; i < n + 1; i++) {
            arr[i] = (int) (Math.log(i) / Math.log(2) + 1e-10);
        }
        return arr;
    }

    private static int log[] = getLogArr(MAXN);

    private static int getLRSpt(int st[][], int L, int R, BinaryOperator<Integer> binaryOperator) {
        int j = log[R - L + 1];
        return binaryOperator.apply(st[L][j], st[R - (1 << j) + 1][j]);
    }

    private static int[][] getSparseTable(int array[], BinaryOperator<Integer> binaryOperator) {
        int k = log[array.length + 1] + 1;
        int st[][] = new int[array.length + 1][k + 1];

        for (int i = 0; i < array.length; i++)
            st[i][0] = array[i];

        for (int j = 1; j <= k; j++) {
            for (int i = 0; i + (1 << j) <= array.length; i++) {
                st[i][j] = binaryOperator.apply(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
            }
        }
        return st;
    }

    static class Subset {
        int parent;
        int rank;

        @Override
        public String toString() {
            return "" + parent;
        }
    }

    static int find(Subset[] Subsets, int i) {
        if (Subsets[i].parent != i)
            Subsets[i].parent = find(Subsets, Subsets[i].parent);
        return Subsets[i].parent;
    }

    static void union(Subset[] Subsets, int x, int y) {
        int xroot = find(Subsets, x);
        int yroot = find(Subsets, y);

        if (Subsets[xroot].rank < Subsets[yroot].rank)
            Subsets[xroot].parent = yroot;
        else if (Subsets[yroot].rank < Subsets[xroot].rank)
            Subsets[yroot].parent = xroot;
        else {
            Subsets[xroot].parent = yroot;
            Subsets[yroot].rank++;
        }
    }

    private static int maxx(Integer... a) {
        return Collections.max(Arrays.asList(a));
    }

    private static int minn(Integer... a) {
        return Collections.min(Arrays.asList(a));
    }

    private static long maxx(Long... a) {
        return Collections.max(Arrays.asList(a));
    }

    private static long minn(Long... a) {
        return Collections.min(Arrays.asList(a));
    }

    private static class Pair<T, U> implements Comparable<Pair<T, U>> {
        T a;
        U b;

        public Pair(T a, U b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pair pair = (Pair) o;
            return a.equals(pair.a) &&
                    b.equals(pair.b);
        }

        @Override
        public int hashCode() {
            return Objects.hash(a, b);
        }

        @Override
        public String toString() {
            return "(" + a +
                    "," + b +
                    ')';
        }

        @Override
        public int compareTo(Pair<T, U> o) {
            return (int) (this.a.equals(o.a) ?
                    this.b.equals(o.b) ? 0 :
                            ((Integer) this.b - (Integer) o.b) / Math.abs((Integer) this.b - (Integer) o.b) :
                    ((Integer) this.a - (Integer) o.a) / Math.abs((Integer) this.a - (Integer) o.a));
        }
    }

    public static int upperBound(List<Integer> list, int value) {
        int low = 0;
        int high = list.size();
        while (low < high) {
            final int mid = (low + high) / 2;
            if (value >= list.get(mid)) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return low;
    }

    private static int[] getLPSArray(String pattern) {
        int i, j, n = pattern.length();
        int[] lps = new int[pattern.length()];
        lps[0] = 0;
        for (i = 1, j = 0; i < n; ) {
            if (pattern.charAt(i) == pattern.charAt(j)) {
                lps[i++] = ++j;
            } else if (j > 0) {
                j = lps[j - 1];
            } else {
                lps[i++] = 0;
            }
        }
        return lps;
    }

    private static List<Integer> findPattern(String text, String pattern) {
        List<Integer> matchedIndexes = new ArrayList<>();
        if (pattern.length() == 0) {
            return matchedIndexes;
        }
        int[] lps = getLPSArray(pattern);
        int i = 0, j = 0, n = text.length(), m = pattern.length();
        while (i < n) {
            if (text.charAt(i) == pattern.charAt(j)) {
                i++;
                j++;
            }
            if (j == m) {
                matchedIndexes.add(i - j);
                j = lps[j - 1];
            }
            if (i < n && text.charAt(i) != pattern.charAt(j)) {
                if (j > 0) {
                    j = lps[j - 1];
                } else {
                    i++;
                }
            }
        }
        return matchedIndexes;
    }

    private static Set<Long> getDivisors(long n) {
        Set<Long> divisors = new HashSet<>();
        divisors.add(1L);
        divisors.add(n);
        for (long i = 2; i <= Math.sqrt(n); i++) {
            if (n % i == 0) {
                divisors.add(i);
                divisors.add(n / i);
            }
        }
        return divisors;
    }

    private static long getLCM(long a, long b) {
        return (Math.max(a, b) / gcd(a, b)) * Math.min(a, b);
    }

    static long fac[] = new long[2000005];
    static long ifac[] = new long[2000005];

    private static void preCompute(int n) {
        fac = new long[n + 1];
        ifac = new long[n + 1];
        fac[0] = ifac[0] = fac[1] = ifac[1] = 1;
        int i;
        for (i = 2; i < n + 1; i++) {
            fac[i] = (i * fac[i - 1]) % mod;
            ifac[i] = (power(i, mod - 2) * ifac[i - 1]) % mod;
        }
    }

    private static long C(int n, int r) {
        if (n < 0 || r < 0) return 1;
        if (r > n) return 1;
        return (fac[n] * ((ifac[r] * ifac[n - r]) % mod)) % mod;
    }

    static long getSum(long BITree[], int index)
    {
        long sum = 0;
        index = index + 1;
        while(index>0)
        {
            index -= index & (-index);
        }
        return sum;
    }

    public static void updateBIT(long BITree[], int index, long val)
    {
        index = index + 1;
        while(index <= BITree.length-1) {
            BITree[index] += val;
            index += index & (-index);
        }
    }
    long[] constructBITree(int arr[], int m)
    {
        int n=arr.length;
        long BITree[] = new long[m+1];
        for(int i=1; i<=n; i++)
            BITree[i] = 0;
        for(int i = 0; i < n; i++)
            updateBIT(BITree, i, arr[i]);
        return BITree;
    }

    private static int upperBound(int a[], int l, int r, int x) {
        if(l>r)return -1;
        if(l==r){
            if(a[l]<=x) {
                return -1;
            }
            else{
                return a[l];
            }
        }
        int m=(l+r)/2;
        if(a[m]<=x) {
            return upperBound(a, m+1,r,x);
        }
        else {
            return upperBound(a, l,m,x);
        }
    }

    private static long getCntOdd(long x, long y)
    {
        long p2 = 1;
        long ans = 0;
        while (p2 * x <= y)
        {
            long hi = Math.min (y, p2 * (x + 1) - 1);
            ans += hi - p2 * x + 1;
            p2 *= 2;
        }
        return ans;
    }

    private static long getCnt(long x, long y)
    {
        long ans=getCntOdd(x,y);
        if(x%2==0) ans+=getCntOdd(x+1,y);
        //System.out.println(ans);
        return ans;
    }

    private static void mul(long A[][], long B[][]){
        int i,j,k,n=A.length;
        long C[][]=new long[n][n];
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                for(k=0;k<n;k++){
                    C[i][j]=(C[i][j]+(A[i][k]*B[k][j])%mod)%mod;
                }
            }
        }
        for(i=0;i<n;i++) {
            for (j = 0; j < n; j++) {
                A[i][j]=C[i][j];
            }
        }
    }

    private static void power(long A[][], long base[][], long n) {
        if(n<2){
            return;
        }
        power(A, base, n/2);
        mul(A,A);
        if(n%2==1){
            mul(A, base);
        }
    }

    public static void main(String[] args) throws Exception {

        long START_TIME = System.currentTimeMillis();
        try (FastReader in = new FastReader();
             FastWriter out = new FastWriter()) {

            int t, i, j,f, k,m, ti, tidx, gm, q, g;
            //for (t = in.nextInt(), tidx = 1; tidx <= t; tidx++)
            {
                long n,w,x, y = 0, z = 0, sum = 0, bhc = 0, ans = 0,l,r;
                //out.print(String.format("Case #%d: ", tidx));
                n=in.nextLong();
                m=in.nextInt();
                long baseMat[][]=new long[m][m];
                long baseMat1[][]=new long[m][m];
                baseMat1[0][0]=baseMat1[0][m-1]=baseMat[0][0]=baseMat[0][m-1]=1;
                for(i=1,j=0;i<m;i++,j++){
                    baseMat1[i][j]=baseMat[i][j]=1;
                }
                if(n<m){
                    out.println(1);
                }
                else {
                    power(baseMat, baseMat1, n);
                    out.println(baseMat[0][0]);
                }

            }
            if (args.length > 0 && "ex_time".equals(args[0])) {
                out.print("\nTime taken: ");
                out.println(System.currentTimeMillis() - START_TIME);
            }
            out.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static class FastReader implements Closeable {
        private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer st;

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        int[] nextIntArr(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextInt();
            }
            return arr;
        }

        int[] nextIntegerArr(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextInt();
            }
            return arr;
        }

        double[] nextDoubleArr(int n) {
            double[] arr = new double[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextDouble();
            }
            return arr;
        }

        long[] nextLongArr(int n) {
            long[] arr = new long[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLong();
            }
            return arr;
        }

        String[] nextStrArr(int n) {
            String[] arr = new String[n];
            for (int i = 0; i < n; i++) {
                arr[i] = next();
            }
            return arr;
        }

        long[][] nextLongArr2(int n, int m) {
            long[][] arr = new long[n][m];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLongArr(m);
            }
            return arr;
        }

        @Override
        public void close() throws IOException {
            br.close();
        }
    }

    public static class FastWriter implements Closeable {
        BufferedWriter bw;
        StringBuilder sb = new StringBuilder();
        List<String> list = new ArrayList<>();
        Set<String> set = new HashSet<>();

        public FastWriter() {
            bw = new BufferedWriter(new OutputStreamWriter(System.out));
        }

        <T> void commit() throws IOException {
            bw.write(sb.toString());
            bw.flush();
            sb = new StringBuilder();
        }

        public <T> void print(T obj) throws IOException {
            sb.append(obj.toString());
        }

        public void println() throws IOException {
            print("\n");
        }

        public <T> void println(T obj) throws IOException {
            print(obj.toString() + "\n");
        }

        <T> void printArrLn(T[] arr) throws IOException {
            for (int i = 0; i < arr.length - 1; i++) {
                print(arr[i] + " ");
            }
            println(arr[arr.length - 1]);
        }

        <T> void printArr2(T[][] arr) throws IOException {
            for (int j = 0; j < arr.length; j++) {
                for (int i = 0; i < arr[j].length - 1; i++) {
                    print(arr[j][i] + " ");
                }
                println(arr[j][arr.length - 1]);
            }
        }

        <T> void printColl(Collection<T> coll) throws IOException {
            for (T e : coll) {
                print(e + " ");
            }
            println();
        }

        void printCharN(char c, int n) throws IOException {
            for (int i = 0; i < n; i++) {
                print(c);
            }
        }

        void printIntArr2(int[][] arr) throws IOException {
            for (int j = 0; j < arr.length; j++) {
                for (int i = 0; i < arr[j].length - 1; i++) {
                    print(arr[j][i] + " ");
                }
                println(arr[j][arr.length - 1]);
            }
        }

        @Override
        public void close() throws IOException {
            bw.close();
        }

    }

}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author cunbidun
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DMagicGems solver = new DMagicGems();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems {
        private static final long MOD = (long) 1e9 + 7;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long n = in.nextLong();
            int m = in.nextInt();
            int[][] columnVector = new int[m + 1][2];
            int[][] base = new int[m + 1][m + 1];

            for (int i = 1; i <= m; i++) {
                columnVector[i][1] = 1;
                for (int j = 1; j <= m; j++) {
                    if (i >= j) base[i][j] = 1;
                }
                base[i][m] = 1;
            }
            base[m][m] = 2;

//        for (int i = 1; i <= m; i++) {
//            for (int j = 1; j <= m; j++) {
//                out.print(base[i][j] + " ");
//            }
//            out.println();
//        }
//        out.println();
            long power;
            if ((n + 1) % m != 0) power = (n + 1) / m;
            else power = ((n + 1) / m) - 1;
            int[][] powerBase = MatrixOperation.powMatrix(base, power, (int) MOD);
            int[][] ansVector = MatrixOperation.mulMatrixMatrix(powerBase, columnVector, (int) MOD);

//        for (int i = 1; i <= m; i++) {
//            for (int j = 1; j <= m; j++) {
//                out.print(powerBase[i][j] + " ");
//            }
//            out.println();
//        }
//        out.println();
            int tmp = (int) ((n + 1) % m);
            if (tmp == 0) tmp = m;
            out.println(ansVector[tmp][1]);
        }

    }

    static class InputReader extends InputStream {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        private static boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

    }

    static class Op {
        public static int addMod(int x, int y, int MOD) {
            return (x + y) % MOD;
        }

        public static int mulMod(int x, int y, int MOD) {
            return (int) (((long) (x % MOD) * (y % MOD)) % MOD);
        }

    }

    static class MatrixOperation {
        public static int[][] mulMatrixMatrix(int[][] x, int[][] y, int MOD) {
            int xR = x.length - 1;
            int xC = x[1].length - 1;
            int yC = y[1].length - 1;
            int[][] ans = new int[xR + 1][yC + 1];
            for (int i = 1; i <= xR; i++) {
                for (int j = 1; j <= yC; j++) {
                    for (int l = 1; l <= xC; l++) {
                        ans[i][j] = Op.addMod(ans[i][j], Op.mulMod(x[i][l], y[l][j], MOD), MOD);
                    }
                }
            }
            return ans;
        }

        public static int[][] powMatrix(int[][] x, long n, int MOD) {
            if (n == 0) {
                int len = x.length - 1;
                int[][] I = new int[len + 1][len + 1];
                for (int i = 1; i <= len; i++) {
                    I[i][i] = 1;
                }
                return I;
            }
            if (n == 1) return x;
            int[][] t = powMatrix(x, n / 2, MOD);
            return mulMatrixMatrix(mulMatrixMatrix(t, t, MOD), powMatrix(x, n % 2, MOD), MOD);
        }

    }
}

import java.io.*;
import java.util.*;

public class A {

	static int[][] matMult(int[][] A, int[][] B) {
		int p = A.length, q = A[0].length, r = B[0].length;
		int[][] ans = new int[p][r];
		for (int i = 0; i < p; i++)
			for (int k = 0; k < q; k++)
				for (int j = 0; j < r; j++)
				{
					ans[i][j] += A[i][k] * 1L * B[k][j] % MOD;
					if (ans[i][j] >= MOD)
						ans[i][j] -= MOD;
				}
		return ans;
	}

	static int[][] pow(int[][] A, long e) {
		int n = A.length;
		int[][] ans = new int[n][n];
		for (int i = 0; i < n; i++)
			ans[i][i] = 1;
		while (e > 0) {
			if ((e & 1) == 1) {
				ans = matMult(ans, A);
			}
			e >>= 1;
			A = matMult(A, A);
		}
		return ans;
	}

	static int MOD = (int) 1e9 + 7;

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		long n = sc.nextLong();
		int m = sc.nextInt();
		if (m > n) {
			System.out.println(1);
			return;
		}
		int[][] A = new int[m][m];
		A[0][0] = A[0][m - 1] = 1;
		for (int i = 1; i < m; i++)
			A[i][i - 1] = 1;
		int[][] B = new int[m][1];
		for (int i = 0; i < m; i++)
			B[i][0] = 1;
		long k = n - m + 1;

		int[][] ans = matMult(pow(A, k), B);
		out.println(ans[0][0]);

		out.close();
	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}
	}
}

import java.io.*;
import java.util.*;

public class A{

	static int[][] matMult(int [][]A,int [][]B) {
		int p=A.length,q=A[0].length,r=B[0].length;
		int [][]ans=new int [p][r];
		for(int i=0;i<p;i++)
			for(int j=0;j<r;j++)
			{
				long curr=0;
				for(int k=0;k<q;k++)
				{
					curr+=A[i][k]*1L*B[k][j];
					curr%=MOD;
				}
				ans[i][j]=(int)curr;

			}
		return ans;
	}
	static int [][]pow(int [][]A,long e) {
		int n=A.length;
		int [][]ans=new int [n][n];
		for(int i=0;i<n;i++)
			ans[i][i]=1;
		while(e>0) {
			if((e&1)==1) {
				ans=matMult(ans, A);
			}
			e>>=1;
			A=matMult(A, A);
		}
		return ans;
	}
	static int MOD=(int)1e9+7;
	public static void main(String[] args) throws IOException {
		Scanner sc=new Scanner();
		PrintWriter out=new PrintWriter(System.out);
		long n=sc.nextLong();
		int m=sc.nextInt();
		if(m>n) {
			System.out.println(1);
			return;
		}
		int [][]A=new int [m][m];
		A[0][0]=A[0][m-1]=1;
		for(int i=1;i<m;i++)
			A[i][i-1]=1;
		int [][]B=new int [m][1];
		for(int i=0;i<m;i++)
			B[i][0]=1;
		long k=n-m+1;

		int [][]ans=matMult(pow(A, k),B);
		out.println(ans[0][0]);

		out.close();
	}
	static class Scanner
	{
		BufferedReader br;
		StringTokenizer st;
		Scanner(){
			br=new BufferedReader(new InputStreamReader(System.in));
		}
		Scanner(String fileName) throws FileNotFoundException{
			br=new BufferedReader(new FileReader(fileName));
		}
		String next() throws IOException {
			while(st==null || !st.hasMoreTokens())
				st=new StringTokenizer(br.readLine());
			return st.nextToken();
		}
		String nextLine() throws IOException {
			return br.readLine();
		}
		int nextInt() throws IOException{
			return Integer.parseInt(next());
		}
		long nextLong()  throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}
		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}
	}
}

import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class Main {
    static final long MOD = 1_000_000_007, INF = 1_000_000_000_000_000_000L;
    static final int INf = 1_000_000_000;
    static FastReader reader;
    static PrintWriter writer;
    public static void main(String[] args) {
        Thread t = new Thread(null, new O(), "Integer.MAX_VALUE", 100000000);
        t.start();
    }
    static class O implements Runnable {
        public void run() {
            try {
                magic();
            }
            catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    }
    static class FastReader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public FastReader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public FastReader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[1000000];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
    static void magic() throws IOException{
        reader = new FastReader();
        writer = new PrintWriter(System.out, true);
        long N = reader.nextLong();
        int M = reader.nextInt();
        long a[] = new long[M];
        a[0] = a[M-1] = 1;
//        writer.println("a : ");
//        for(int i=0;i<M;++i) {
//            writer.print(a[i]+" ");
//        }
//        writer.println();
        long f[] = new long[M];
        Arrays.fill(f, 1);
        writer.println(findNthTerm(N, a, f, M, 0));
    }

    /**
     *
     * @param N
     * @param a the array a[] representing the coefficients a1,a2,a3,...ak
     * @param d the constant term in the recurrence
     * @param f the initial k values of the function i.e. f(0), f(1), f(2)....f(k-1)
     * @returns the Nth term of the recurrence: f(n) = a1*f(n-1) + a2*f(n-2) + ... + ak*f(n-k) + d
     * Complexity: O(k^3 * log(N))
     */
    static long findNthTerm(long N, long a[], long f[], int k, long d) {
        long mat[][] = new long[k+1][k+1];
        mat[0][0] = 1;
        for(int col=1;col<=k;++col) {
            if(col==k) {
                mat[0][col] = d;
                for(int row=1;row<=k;++row) {
                    mat[row][col] = a[k-row];
                }
            }
            else {
                mat[col+1][col] = 1;
            }
        }
//        writer.println("Matrix: ");
//        for(int i=0;i<=k;++i) {
//            for(int j=0;j<=k;++j) {
//                writer.print(mat[i][j]+" ");
//            }
//            writer.println();
//        }
        if(N<k) {
           return f[(int)N];
        }
        else {
            long M[][] = exponentiateMatrix(mat, k+1, N-k+1);
            long res[] = new long[k+1];
            for(int i=0;i<=k;++i) {
                long multiplier;
                if(i==0) {
                    multiplier = 1;
                }
                else {
                    multiplier = f[i-1];
                }
                for(int j=0;j<=k;++j) {
                    res[i] = (res[i] + multiplier * M[j][i])%MOD;
                }
            }
            return res[k];
        }
    }

    /**
     *
     * @param a
     * @param b
     * @param k
     * @return the product of the two (k*k) matrices a and b
     */
    static long[][] multiply(long a[][], long b[][], int k) {
        long c[][] = new long[k][k];
        for(int i=0;i<k;++i) {
            for(int j=0;j<k;++j) {
                for(int K=0;K<k;++K) {
                    c[i][j] = (c[i][j] + a[i][K]*b[K][j])%MOD;
                }
            }
        }
        return c;
    }

    /**
     *
     * @param mat
     * @param k
     * @param n
     * @return Finds the matrix: mat^n, here mat is a (k*k) matrix
     */
    static long[][] exponentiateMatrix(long mat[][], int k, long n) {
        if(n==1) {
            return mat;
        }
        if(n%2==0) {
            long half[][] = exponentiateMatrix(mat, k, n/2);
            return multiply(half, half, k);
        }
        return multiply(mat, exponentiateMatrix(mat,k, n-1), k);
    }
}

import java.util.Arrays;
import java.util.Scanner;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Andy Phan
 */
public class p1117d {
    static long MOD = 1000000007;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        long n = in.nextLong();
        int m = in.nextInt();
        long[][] exp = new long[m+1][m+1];
        for(int i = 0; i < m; i++) {
            exp[i+1][i] = 1;
        }
        exp[1][m] = 1;
        exp[m][m] = 1;
        long[][] a = new long[1][m+1];
        a[0][m] = 1;
        a = mult(a, expo(exp, n));
        System.out.println(a[0][m]);
    }

    static long[][] expo(long[][] base, long pow) {
        if(pow == 1) return base;
        long[][] tmp = expo(base, pow>>1);
        long[][] ret = mult(tmp, tmp);
        if((pow&1) != 0) ret = mult(ret, base);
        return ret;
    }

    static long[][] mult(long[][] a, long[][] b) {
        long[][] ret = new long[a.length][b[0].length];
        for(int i = 0; i < a.length; i++) {
            for(int j = 0; j < b[0].length; j++) {
                long tot = 0;
                for(int k = 0; k < b.length; k++) {
                    tot += a[i][k]*b[k][j];
                    tot %= MOD;
                }
                ret[i][j] = tot;
            }
        }
        return ret;
    }
}

import java.util.*;

public class D1117 {
	static long[][] transition;
	static int m;
	static long mod = (long) (1e9) + 7;

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		//System.out.println(mod);
		long n = in.nextLong();
		m = in.nextInt();
		transition = new long[m][m];
		transition[0][0] = 1;
		transition[0][m - 1] = 1;
		for (int i = 0; i < m -1; i++) {
			transition[i+1][i] = 1;
		}
		//System.out.println(Arrays.deepToString(transition));
		long[][] initial = Arrays.copyOf(transition, m);
		long[][] ans = fmp(initial, n);
		//System.out.println(Arrays.deepToString(ans));
		System.out.println(ans[0][0]);
	}

	static long[][] fmp(long[][] matrix, long pow) {
		//System.out.println("cur pow: " + pow);
		//System.out.println(Arrays.deepToString(matrix));
		if (pow == 1)
			return matrix;

		matrix = fmp(matrix, pow / 2);
		long[][] next = new long[m][m];
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < m; j++) {
				long sum = 0;
				for (int k = 0; k < m; k++) {
					sum += (matrix[i][k] * matrix[k][j])%mod;
					sum %= mod;
				}
				next[i][j] = sum % mod;
			}
		}
		if(pow % 2 == 0) {
			return next;
		}

		long[][] n2 = new long[m][m];
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < m; j++) {
				long sum = 0;
				for (int k = 0; k < m; k++) {
					sum += (next[i][k] * transition[k][j])%mod;
					sum %= mod;
				}
				n2[i][j] = sum % mod;
			}
		}

		return n2;

	}

}

import java.io.*;
import java.util.*;

public class D
{

	static StringBuilder st = new StringBuilder();

	// dp(n ) = dp(n - 1) ->> put normal gem   + dp(n - m ) -->> divide magic gem to m elements

	static final int MOD = (int)1e9 + 7 ;
	static int [][] mat ;

	public static void main(String[] args) throws Exception
	{
		Scanner sc = new Scanner(System.in) ;
		PrintWriter out = new PrintWriter(System.out) ;

		long n = sc.nextLong() ; int m = sc.nextInt() ;

		mat = new int [m][m] ;

		mat[0][0] = 1 ; mat[0][m - 1] = 1 ;

		for(int i = 1 ;i < m ;i++) mat[i][i - 1] = 1 ;

		if(n < m)
			out.println(1);
		else
			out.println(pow(mat, n - m , m));

		out.flush();
		out.close();

	}

	static int pow(int [][] mat , long n , int m)
	{
		int [][] res = new int [m][m] ;

		for(int i = 0 ;i < m ; i++) res [i] = mat[i].clone() ;

		while(n > 0)
		{
			if((n & 1) == 1)
				res = mult(mat, res) ;

			mat = mult(mat , mat) ;
			n >>= 1  ;
		}

		int ans = 0 ;
		for(int l = 0 ; l < m ; l ++ )
			ans = (ans + res[0][l]) % MOD ;

		return (ans % MOD);
	}

	static int [][] mult(int [][] a , int [][] b)
	{
		int [][] res = new int [a.length][a.length] ;
		int m = a.length ;

		for(int i = 0 ;i < m; i ++)
			for(int j = 0 ; j < m ; j ++ )
				for(int l = 0 ; l < m ; l++)
				{
					res[i][j] += (int)((1l * a[i][l] * b[l][j] % MOD)) ;
					res[i][j] %= MOD ;
				}

		return res ;
	}
	static class Scanner
	{
		BufferedReader br;
		StringTokenizer st;

		Scanner(InputStream in)
		{
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		String next() throws Exception
		{
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		int nextInt() throws Exception { return Integer.parseInt(next()); }

		long nextLong() throws Exception { return Long.parseLong(next()); }

		double nextDouble() throws Exception { return Double.parseDouble(next());}

	}

	static void shuffle(int[] a)
	{
		int n = a.length;
		for (int i = 0; i < n; i++)
		{
			int r = i + (int) (Math.random() * (n - i));
			int tmp = a[i];
			a[i] = a[r];
			a[r] = tmp;
		}
	}

}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author real
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        long mod;
        long[][] firstm;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long n = in.nextLong();
            int m = in.nextInt();
            mod = in.mod1e97;
            firstm = new long[m][1];
            for (int i = 0; i < m; i++) {
                firstm[i][0] = 1;
            }
            if (n < m) {
                out.print(firstm[(int) n][0]);
                return;
            }
            long matrix[][] = new long[m][m];
            for (int i = 1; i < m; i++) {
                matrix[i][i - 1] = 1;
            }
            matrix[0][m - 1] = 1;
            matrix[0][0] = 1;
            long po = n - m + 1;
            long ans[][] = pow(matrix, po);
            long ans2[][] = multiply(ans, firstm);
            out.print(ans2[0][0]);
        }

        long[][] pow(long matrix[][], long m) {
            if (m == 1)
                return matrix;
            if (m % 2 == 0) {
                long mat[][] = pow(matrix, m / 2);
                return multiply(mat, mat);
            }
            return multiply(matrix, pow(matrix, m - 1));
        }

        long[][] multiply(long matrix1[][], long matrix2[][]) {
            long ans[][] = new long[matrix1.length][matrix2[0].length];
            for (int i = 0; i < matrix1.length; i++) {
                for (int j = 0; j < matrix2[0].length; j++) {
                    for (int k = 0; k < matrix1[0].length; k++) {
                        ans[i][j] += (matrix1[i][k] * matrix2[k][j]) % mod;
                        ans[i][j] = ans[i][j] % mod;
                    }
                }
            }
            return ans;
        }

    }

    static class InputReader {
        private final InputStream stream;
        private final byte[] buf = new byte[8192];
        private int curChar;
        private int snumChars;
        int mod1e97 = (int) 1e9 + 7;

        public InputReader(InputStream st) {
            this.stream = st;
        }

        public int read() {
            //*-*------clare------
//remeber while comparing 2 non primitive data type not to use ==
//remember Arrays.sort for primitive data has worst time case complexity of 0(n^2) bcoz it uses quick sort
//again silly mistakes ,yr kb tk krta rhega ye mistakes
//try to write simple codes ,break it into simple things
            // for test cases make sure println(); ;)
//knowledge>rating
        /*
        public class Main
        implements Runnable{
    public static void main(String[] args) {
        new Thread(null,new Main(),"Main",1<<26).start();

    }
    public void run() {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskC solver = new TaskC();//chenge the name of task
        solver.solve(1, in, out);
        out.close();
    }
         */

            if (snumChars == -1)
                throw new InputMismatchException();
            if (curChar >= snumChars) {
                curChar = 0;
                try {
                    snumChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (snumChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            TaskD solver = new TaskD();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class TaskD {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            long n = in.readLong();
            int m = in.readInt();
            Modular mod = new Modular(1e9 + 7);
            ModMatrix vec = new ModMatrix(m, 1);
            for (int i = 0; i < m; i++) {
                vec.set(i, 0, 1);
            }
            ModMatrix single = new ModMatrix(m, m);
            for (int i = 0; i < m - 1; i++) {
                single.set(i, i + 1, 1);
            }
            single.set(m - 1, 0, 1);
            single.set(m - 1, m - 1, 1);

            ModMatrix multi = ModMatrix.pow(single, n, mod);
            ModMatrix ans = ModMatrix.mul(multi, vec, mod);
            out.println(ans.get(0, 0));
        }

    }

    static class ModMatrix {
        int[][] mat;
        int n;
        int m;

        public ModMatrix(ModMatrix model) {
            n = model.n;
            m = model.m;
            mat = new int[n][m];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    mat[i][j] = model.mat[i][j];
                }
            }
        }

        public ModMatrix(int n, int m) {
            this.n = n;
            this.m = m;
            mat = new int[n][m];
        }

        public ModMatrix(int[][] mat) {
            if (mat.length == 0 || mat[0].length == 0) {
                throw new IllegalArgumentException();
            }
            this.n = mat.length;
            this.m = mat[0].length;
            this.mat = mat;
        }

        public void fill(int v) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    mat[i][j] = v;
                }
            }
        }

        public void asStandard(Modular mod) {
            fill(0);
            if (mod.getMod() == 1) {
                return;
            }
            for (int i = 0; i < n && i < m; i++) {
                mat[i][i] = 1;
            }
        }

        public void set(int i, int j, int val) {
            mat[i][j] = val;
        }

        public int get(int i, int j) {
            return mat[i][j];
        }

        public static ModMatrix mul(ModMatrix a, ModMatrix b, Modular modular) {
            ModMatrix c = new ModMatrix(a.n, b.m);
            for (int i = 0; i < c.n; i++) {
                for (int j = 0; j < c.m; j++) {
                    for (int k = 0; k < a.m; k++) {
                        c.mat[i][j] = modular.plus(c.mat[i][j], modular.mul(a.mat[i][k], b.mat[k][j]));
                    }
                }
            }
            return c;
        }

        public static ModMatrix pow(ModMatrix x, long n, Modular modular) {
            if (n == 0) {
                ModMatrix r = new ModMatrix(x.n, x.m);
                r.asStandard(modular);
                return r;
            }
            ModMatrix r = pow(x, n >> 1, modular);
            r = ModMatrix.mul(r, r, modular);
            if (n % 2 == 1) {
                r = ModMatrix.mul(r, x, modular);
            }
            return r;
        }

        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    builder.append(mat[i][j]).append(' ');
                }
                builder.append('\n');
            }
            return builder.toString();
        }

    }

    static class Modular {
        int m;

        public int getMod() {
            return m;
        }

        public Modular(int m) {
            this.m = m;
        }

        public Modular(long m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public Modular(double m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public int valueOf(int x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return x;
        }

        public int valueOf(long x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return (int) x;
        }

        public int mul(int x, int y) {
            return valueOf((long) x * y);
        }

        public int plus(int x, int y) {
            return valueOf(x + y);
        }

        public String toString() {
            return "mod " + m;
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public long readLong() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            long val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collection;
import java.io.IOException;
import java.util.Deque;
import java.util.function.Supplier;
import java.io.UncheckedIOException;
import java.util.function.Consumer;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.ArrayDeque;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            TaskD solver = new TaskD();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class TaskD {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            long n = in.readLong();
            int m = in.readInt();
            Modular mod = new Modular(1e9 + 7);
            int[][] dp = new int[m * 2][m];
            Arrays.fill(dp[0], 1);
            for (int i = 1; i < 2 * m; i++) {
                for (int j = 0; j < m - 1; j++) {
                    dp[i][j] = dp[i - 1][j + 1];
                }
                dp[i][m - 1] = mod.plus(dp[i - 1][m - 1], dp[i - 1][0]);
            }
            ModLinearFeedbackShiftRegister lfsr = new ModLinearFeedbackShiftRegister(mod, 2 * m);
            for (int i = 0; i < 2 * m; i++) {
                lfsr.add(dp[i][0]);
            }
            IntList p = new IntList(lfsr.length() + 1);
            for (int i = 0; i < lfsr.length(); i++) {
                p.add(mod.valueOf(-lfsr.codeAt(lfsr.length() - i)));
            }
            p.add(1);

            IntList remainder = new IntList(m * 2);
            Polynomials.module(n, p, remainder, new Power(mod));

            long ans = 0;
            for (int i = 0; i < remainder.size(); i++) {
                ans = mod.plus(ans, mod.mul(remainder.get(i), dp[i][0]));
            }

            out.println(ans);
        }

    }

    static class Modular {
        int m;

        public Modular(int m) {
            this.m = m;
        }

        public Modular(long m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public Modular(double m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public int valueOf(int x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return x;
        }

        public int valueOf(long x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return (int) x;
        }

        public int mul(int x, int y) {
            return valueOf((long) x * y);
        }

        public int plus(int x, int y) {
            return valueOf(x + y);
        }

        public int plus(long x, long y) {
            x = valueOf(x);
            y = valueOf(y);
            return valueOf(x + y);
        }

        public int subtract(int x, int y) {
            return valueOf(x - y);
        }

        public String toString() {
            return "mod " + m;
        }

    }

    static class ModLinearFeedbackShiftRegister {
        private IntList cm;
        int m = -1;
        int dm;
        private IntList cn;
        private IntList buf;
        private IntList seq;
        private Modular mod;
        private Power pow;

        public ModLinearFeedbackShiftRegister(Modular mod, int cap) {
            cm = new IntList(cap + 1);
            cn = new IntList(cap + 1);
            seq = new IntList(cap + 1);
            buf = new IntList(cap + 1);
            cn.add(1);

            this.mod = mod;
            this.pow = new Power(mod);
        }

        public ModLinearFeedbackShiftRegister(Modular mod) {
            this(mod, 0);
        }

        private int estimateDelta() {
            int n = seq.size() - 1;
            int ans = 0;
            int[] cnData = cn.getData();
            int[] seqData = seq.getData();
            for (int i = 0, until = cn.size(); i < until; i++) {
                ans = mod.plus(ans, mod.mul(cnData[i], seqData[n - i]));
            }
            return ans;
        }

        public void add(int x) {
            x = mod.valueOf(x);
            int n = seq.size();

            seq.add(x);
            int dn = estimateDelta();
            if (dn == 0) {
                return;
            }

            if (m < 0) {
                cm.clear();
                cm.addAll(cn);
                dm = dn;
                m = n;

                cn.expandWith(0, n + 2);
                return;
            }

            int ln = cn.size() - 1;
            int len = Math.max(ln, n + 1 - ln);
            buf.clear();
            buf.addAll(cn);
            buf.expandWith(0, len + 1);

            int factor = mod.mul(dn, pow.inverse(dm));

            int[] bufData = buf.getData();
            int[] cmData = cm.getData();
            for (int i = n - m, until = n - m + cm.size(); i < until; i++) {
                bufData[i] = mod.subtract(bufData[i], mod.mul(factor, cmData[i - (n - m)]));
            }

            if (cn.size() < buf.size()) {
                IntList tmp = cm;
                cm = cn;
                cn = tmp;
                m = n;
                dm = dn;
            }
            {
                IntList tmp = cn;
                cn = buf;
                buf = tmp;
            }

        }

        public int length() {
            return cn.size() - 1;
        }

        public String toString() {
            return cn.toString();
        }

        public int codeAt(int i) {
            return mod.valueOf(-cn.get(i));
        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(long c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class IntList {
        private int size;
        private int cap;
        private int[] data;
        private static final int[] EMPTY = new int[0];

        public int[] getData() {
            return data;
        }

        public IntList(int cap) {
            this.cap = cap;
            if (cap == 0) {
                data = EMPTY;
            } else {
                data = new int[cap];
            }
        }

        public IntList(IntList list) {
            this.size = list.size;
            this.cap = list.cap;
            this.data = Arrays.copyOf(list.data, size);
        }

        public IntList() {
            this(0);
        }

        public void ensureSpace(int req) {
            if (req > cap) {
                while (cap < req) {
                    cap = Math.max(cap + 10, 2 * cap);
                }
                data = Arrays.copyOf(data, cap);
            }
        }

        private void checkRange(int i) {
            if (i < 0 || i >= size) {
                throw new ArrayIndexOutOfBoundsException();
            }
        }

        public int get(int i) {
            checkRange(i);
            return data[i];
        }

        public void add(int x) {
            ensureSpace(size + 1);
            data[size++] = x;
        }

        public void addAll(int[] x, int offset, int len) {
            ensureSpace(size + len);
            System.arraycopy(x, offset, data, size, len);
            size += len;
        }

        public void addAll(IntList list) {
            addAll(list.data, 0, list.size);
        }

        public void expandWith(int x, int len) {
            ensureSpace(len);
            while (size < len) {
                data[size++] = x;
            }
        }

        public void retain(int n) {
            if (n < 0) {
                throw new IllegalArgumentException();
            }
            if (n >= size) {
                return;
            }
            size = n;
        }

        public void set(int i, int x) {
            checkRange(i);
            data[i] = x;
        }

        public int size() {
            return size;
        }

        public int[] toArray() {
            return Arrays.copyOf(data, size);
        }

        public void clear() {
            size = 0;
        }

        public String toString() {
            return Arrays.toString(toArray());
        }

        public boolean equals(Object obj) {
            if (!(obj instanceof IntList)) {
                return false;
            }
            IntList other = (IntList) obj;
            return SequenceUtils.equal(data, 0, size - 1, other.data, 0, other.size - 1);
        }

    }

    static class Buffer<T> {
        private Deque<T> deque = new ArrayDeque<>();
        private Supplier<T> supplier;
        private Consumer<T> cleaner;

        public Buffer(Supplier<T> supplier) {
            this(supplier, (x) -> {
            });
        }

        public Buffer(Supplier<T> supplier, Consumer<T> cleaner) {
            this.supplier = supplier;
            this.cleaner = cleaner;
        }

        public T alloc() {
            return deque.isEmpty() ? supplier.get() : deque.removeFirst();
        }

        public void release(T e) {
            cleaner.accept(e);
            deque.addLast(e);
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public long readLong() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            long val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }

    static class Polynomials {
        public static Buffer<IntList> listBuffer = new Buffer<>(IntList::new, list -> list.clear());

        public static int rankOf(IntList p) {
            int[] data = p.getData();
            int r = p.size() - 1;
            while (r >= 0 && data[r] == 0) {
                r--;
            }
            return Math.max(0, r);
        }

        public static void normalize(IntList list) {
            list.retain(rankOf(list) + 1);
        }

        public static void mul(IntList a, IntList b, IntList c, Modular mod) {
            int rA = rankOf(a);
            int rB = rankOf(b);
            c.clear();
            c.expandWith(0, rA + rB + 1);
            int[] aData = a.getData();
            int[] bData = b.getData();
            int[] cData = c.getData();
            for (int i = 0; i <= rA; i++) {
                for (int j = 0; j <= rB; j++) {
                    cData[i + j] = mod.plus(cData[i + j], mod.mul(aData[i], bData[j]));
                }
            }
        }

        public static void divide(IntList a, IntList b, IntList c, IntList remainder, Power pow) {
            Modular mod = pow.getModular();
            int rA = rankOf(a);
            int rB = rankOf(b);

            if (rA < rB) {
                c.clear();
                c.add(0);
                remainder.clear();
                remainder.addAll(a);
                return;
            }

            int rC = Math.max(0, rA - rB);
            c.clear();
            c.expandWith(0, rC + 1);
            remainder.clear();
            remainder.addAll(a);

            int[] bData = b.getData();
            int[] cData = c.getData();
            int[] rData = remainder.getData();

            int inv = pow.inverse(b.get(rB));
            for (int i = rA, j = rC; i >= rB; i--, j--) {
                if (rData[i] == 0) {
                    continue;
                }
                int factor = mod.mul(-rData[i], inv);
                cData[j] = mod.valueOf(-factor);
                for (int k = rB; k >= 0; k--) {
                    rData[k + j] = mod.plus(rData[k + j], mod.mul(factor, bData[k]));
                }
            }

            normalize(remainder);
        }

        public static void module(long k, IntList p, IntList remainder, Power pow) {
            int rP = rankOf(p);
            if (rP == 0) {
                remainder.clear();
                remainder.add(0);
                return;
            }

            IntList a = listBuffer.alloc();
            IntList c = listBuffer.alloc();

            module(k, a, p, c, remainder, rP, pow);

            listBuffer.release(a);
            listBuffer.release(c);
        }

        private static void module(long k, IntList a, IntList b, IntList c, IntList remainder, int rb, Power pow) {
            Modular mod = pow.getModular();
            if (k < rb) {
                remainder.clear();
                remainder.expandWith(0, (int) k + 1);
                remainder.set((int) k, 1);
                return;
            }
            module(k / 2, a, b, c, remainder, rb, pow);
            mul(remainder, remainder, a, mod);
            if (k % 2 == 1) {
                int ra = rankOf(a);
                a.expandWith(0, ra + 2);
                int[] aData = a.getData();
                for (int i = ra; i >= 0; i--) {
                    aData[i + 1] = aData[i];
                }
                aData[0] = 0;
            }
            divide(a, b, c, remainder, pow);
        }

    }

    static class SequenceUtils {
        public static boolean equal(int[] a, int al, int ar, int[] b, int bl, int br) {
            if ((ar - al) != (br - bl)) {
                return false;
            }
            for (int i = al, j = bl; i <= ar; i++, j++) {
                if (a[i] != b[j]) {
                    return false;
                }
            }
            return true;
        }

    }

    static class Power {
        final Modular modular;

        public Modular getModular() {
            return modular;
        }

        public Power(Modular modular) {
            this.modular = modular;
        }

        public int pow(int x, long n) {
            if (n == 0) {
                return modular.valueOf(1);
            }
            long r = pow(x, n >> 1);
            r = modular.valueOf(r * r);
            if ((n & 1) == 1) {
                r = modular.valueOf(r * x);
            }
            return (int) r;
        }

        public int inverse(int x) {
            return pow(x, modular.m - 2);
        }

    }
}

import java.util.*;
public class issam{
    static class consecutive{
        long mod;
        long[][] matrix;
        long nbWays(long n,int m,long mod){
            this.mod = mod;
            if(n<(long)m) return 1;
            if(n==(long)m) return 2;
            if(m==1) return nbPow(2,n);
            matrix = new long[m][m];
            for(int i=1;i<m;i++) matrix[i][i-1] = 1;
            matrix[0][0] = 1;
            matrix[0][m-1] = 1;
            matrix = pow(matrix,n-(long)m+1);
            long ans = 0;
            for(int i=0;i<m;i++){
                ans += matrix[0][i];
                ans %= mod;
            }
            return ans;
        }

        long nbPow(long a,long n){
            if(n==1) return a;
            if(n%2==0){
                long ans = nbPow(a,n/2);
                return (ans*ans)%mod;
            }
            return (a*nbPow(a,n-1))%mod;
        }

        long[][] pow(long matrix[][], long m) {
            if (m == 1)
                return matrix;
            if (m % 2 == 0) {
                long mat[][] = pow(matrix, m / 2);
                return multiply(mat, mat);
            }
            return multiply(matrix, pow(matrix, m - 1));
        }

        long[][] multiply(long matrix1[][], long matrix2[][]) {
            long ans[][] = new long[matrix1.length][matrix2[0].length];
            for (int i = 0; i < matrix1.length; i++) {
                for (int j = 0; j < matrix2[0].length; j++) {
                    for (int k = 0; k < matrix1[0].length; k++) {
                        ans[i][j] += (matrix1[i][k] * matrix2[k][j]) % mod;
                        ans[i][j] = ans[i][j] % mod;
                    }
                }
            }
            return ans;
        }

    }
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        long n = sc.nextLong();
        int m = sc.nextInt();
        consecutive c = new consecutive();
        long mod = 1000;
        mod = mod*mod*mod+7;
        long res = c.nbWays(n,m,mod);
        System.out.println(res);
    }
}

import java.io.*;
import java.util.StringTokenizer;

public class Template {
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);

        long n = sc.nextLong();
        int m = sc.nextInt();

        int[][] init = new int[m][1];
        for (int i = 0; i < init.length; i++)
            init[i][0] = 1;
        int[][] mat = new int[m][m];
        mat[0][0] = mat[0][m-1] = 1;
        for (int i = 1; i < m; i++)
            mat[i][i-1] = 1;

        if(n < m)
            System.out.println(1);
        else
        {
            System.out.println(matMul(matPow(mat, n-m+1), init, m, m, 1)[0][0]);
        }
        pw.flush();
        pw.close();
    }

    static int mod = 1000000007;

    static int[][] matMul(int[][] A, int[][] B, int p, int q, int r)	//C(p x r) = A(p x q) x (q x r) -- O(p x q x r)
    {
        int[][] C = new int[p][r];
        for(int i = 0; i < p; ++i)
            for(int j = 0; j < r; ++j)
                for(int k = 0; k < q; ++k) {
                    C[i][j] += (int) ((1l * A[i][k] * B[k][j]) % mod);
                    C[i][j] %= mod;
                }
        return C;
    }

    /*
     * 4. Square Matrix Exponentiation
     */
    static int[][] matPow(int[][] base, long p)
    {
        int n = base.length;
        int[][] ans = new int[n][n];
        for(int i = 0; i < n; i++)
            ans[i][i] = 1;
        while(p != 0)
        {
            if((p & 1) == 1)
                ans = matMul(ans, base, n, n, n);
            base = matMul(base, base, n, n, n);
            p >>= 1;
        }

        return ans;
    }

    static class Scanner
    {
        StringTokenizer st; BufferedReader br;
        public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}
        public Scanner(String s) throws FileNotFoundException {	br = new BufferedReader(new FileReader(new File(s)));}
        public String next() throws IOException {while (st == null || !st.hasMoreTokens()) st = new StringTokenizer(br.readLine());return st.nextToken();}
        public int nextInt() throws IOException {return Integer.parseInt(next());}
        public long nextLong() throws IOException {return Long.parseLong(next());}
        public String nextLine() throws IOException {return br.readLine();}
        public boolean ready() throws IOException {return br.ready();}
    }
}

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class Main {

	static class Task {

		int NN = 200005;
		int MOD = 1000000007;
		int INF = 2000000000;
		long INFINITY = 2000000000000000000L;

		class Matrix {
			long [][] a;
			int n, m;
			public Matrix(int n, int m) {
				a = new long[n][m];
				this.n = n;this.m = m;
			}

			public Matrix(long [][] d) {
				this.n= d.length;
				this.m = d[0].length;
				a = new long[n][m];
				for(int i=0;i<n;++i) {
					for(int j=0;j<m;++j) {
						a[i][j] = d[i][j];
					}
				}
			}

			public Matrix multiply(Matrix mat) {
				if(this.m != mat.n)
					return null;
				Matrix res = new Matrix(this.n, mat.m);
				for(int i=0;i<this.n;++i) {
					for(int j=0;j<mat.m;++j) {
						long total = 0;
						for(int k=0;k<this.m;++k) {
							total = (total + this.a[i][k]*mat.a[k][j]) % MOD;
						}
						res.a[i][j] = total;
					}
				}
				return res;
			}

			public Matrix unit() {
				Matrix res = new Matrix(this.n, this.m);
				for(int i=0;i<n;++i) {
					for(int j=0;j<m;++j) {
						if(i == j) {
							res.a[i][j] = 1;
						} else {
							res.a[i][j] = 0;
						}
					}
				}
				return res;
			}

			public Matrix clone() {
				Matrix res = new Matrix(this.n, this.m);
				for(int i=0;i<n;++i) {
					for(int j=0;j<m;++j) {
						res.a[i][j] = this.a[i][j];
					}
				}
				return res;
			}

			public Matrix pow(long exponent) {
				Matrix ret = this.unit(), sq = this.clone();
				while(exponent > 0) {
					if(exponent%2 != 0) {
						ret = ret.multiply(sq);
					}
					exponent >>= 1;
					sq = sq.multiply(sq);
				}
				return ret;
			}

		}

		public void solve(InputReader in, PrintWriter out) {
			long N = in.nextLong(), M = in.nextLong();
			if(N < M) {
				out.println(1);return;
			}
			long [][] a = new long[(int)M][1];
			for(int j=0;j<(int)M;++j) {
				a[j][0] = 1;
			}
			Matrix P = new Matrix(a);
			long [][] b = new long[(int)M][(int)M];
			for(int i=0;i<M;++i) {
				for(int j=0;j<M;++j) {
					if(i == 0) {
						if(j == 0 || j == M - 1) {
							b[i][j] = 1;
						} else {
							b[i][j] = 0;
						}
					} else {
						if(i == j + 1) {
							b[i][j] = 1;
						} else {
							b[i][j] = 0;
						}
					}
				}
			}
			Matrix Q = new Matrix(b);
			Matrix ans = Q.pow(N - M + 1L).multiply(P);
			out.println(ans.a[0][0]);
		}
	}

	static void prepareIO(boolean isFileIO) {
		//long t1 = System.currentTimeMillis();
		Task solver = new Task();
		// Standard IO
		if(!isFileIO) {
			InputStream inputStream = System.in;
	        OutputStream outputStream = System.out;
	        InputReader in = new InputReader(inputStream);
	        PrintWriter out = new PrintWriter(outputStream);
	        solver.solve(in, out);
	        //out.println("time(s): " + (1.0*(System.currentTimeMillis()-t1))/1000.0);
	        out.close();
		}
        // File IO
		else {
			String IPfilePath = System.getProperty("user.home") + "/Downloads/ip.in";
	        String OPfilePath = System.getProperty("user.home") + "/Downloads/op.out";
	        InputReader fin = new InputReader(IPfilePath);
	        PrintWriter fout = null;
	        try {
				fout = new PrintWriter(new File(OPfilePath));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
	        solver.solve(fin, fout);
	        //fout.println("time(s): " + (1.0*(System.currentTimeMillis()-t1))/1000.0);
	        fout.close();
		}
	}

	public static void main(String[] args) {
        prepareIO(false);
	}

	static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public InputReader(String filePath) {
        	File file = new File(filePath);
            try {
				reader = new BufferedReader(new FileReader(file));
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
            tokenizer = null;
        }

        public String nextLine() {
        	String str = "";
        	try {
				str = reader.readLine();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        	return str;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public double nextDouble() {
        	return Double.parseDouble(next());
        }

    }

}

import java.util.*;
import java.io.*;

public class MagicGems {
    public static final long MOD = 1000000007L;
    public static final long MODS = MOD*MOD;
    public static void main(String[] args) {
        FastScanner scanner = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);
        long N = scanner.nextLong();
        int M = scanner.nextInt();
        long[][] matrix = new long[M][M];
        for(int i= 0; i  < M-1; i++) {
            matrix[i+1][i] = 1;
        }
        //base cases
        matrix[0][0] = 1;
        matrix[0][M-1] = 1;
        long[] ans = new long[M];
        ans[0] = 1;
        out.println(mPow(matrix, ans, N)[0]);
        out.flush();
    }

    //calculates the power and gets answer from it
    public static long[] mPow (long[][] M,  long[] v, long pow) {
        for(int i= 0; i < v.length; i++) if(v[i] >= MOD) v[i]%=MOD;
        long[][] ret = M;
        //>>>= is an unsigned right shift by 1
        for(;pow> 0; pow >>>=1) {
            if ((pow&1)==1) v = mMul(ret, v);
            //ret = mSquare(ret);
            ret = matrixMul(ret, ret);
        }
        return v;
    }

    public static long[] mMul(long[][] M, long[] v) {
        int m = M.length;
        int n= v.length;
        long[] ret = new long[m];
        for(int i= 0; i < m; i++) {
            long sum = 0;
            for(int k = 0; k < n; k++) {
                sum += M[i][k] * v[k];
                if (sum >= MODS) sum-= MODS;
            }
            ret[i] = sum%MOD;
        }
        return ret;
    }

    //need to be a square matrix
    //should have efficiency based on lacking mod ops.
//    public static long[][] mSquare(long[][] M) {
//        int N = M.length;
//        long[][] ret = new long[N][N];
//        for(int i = 0; i < N; i++) {
//            long[] temp = new long[N];
//            for(int k = 0; k < N; k++) {
//                for(int j = 0; j < N; j++) {
//                    temp[j] += M[i][k] * M[k][j];
//                    if (temp[j] >= MODS) temp[j]-=MODS;
//                }
//            }
//            for(int k = 0; k < N; k++) {
//                ret[i][k] = (temp[k] %MOD);
//            }
//        }
//        return ret;
//    }

    public static long[][] matrixMul(long[][] a, long[][] b) {
        int n = a.length;
        int m = a[0].length;
        int k = b[0].length;
        long[][] res = new long[n][k];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < k; j++) {
                for (int p = 0; p < m; p++) {
                    res[i][j] = (res[i][j] + a[i][p] * b[p][j])%MOD;
                }
            }
        }
        return res;
    }

    public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(Reader in) {
            br = new BufferedReader(in);
        }

        public FastScanner() {
            this(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String readNextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        int[] readIntArray(int n) {
            int[] a = new int[n];
            for (int idx = 0; idx < n; idx++) {
                a[idx] = nextInt();
            }
            return a;
        }
    }
}

import java.util.*;

public class magicGems {
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		//recurrence f(n)-f(n-1)+f(n-m)
		//since you could split the rock (takes m spaces) or not split the rock (takes 1 space)
		long n=scan.nextLong();
		m=scan.nextInt();
		long[][] mat=new long[m][m];
		for(int i=1;i<m;i++) mat[i][i-1]=1;
		mat[0][0]=mat[0][m-1]=1;
		long[][] start=new long[m][1];//answers from 0 to m-1 rocks
		dp=new long[m];//dp[i]=answer for i magic rocks
		Arrays.fill(dp,-1);
		for(int i=m-1;i>=0;i--) go(i);
		for(int i=0;i<m;i++) start[i][0]=dp[i];
		if(n<m) {
			System.out.println(dp[(int)n]);
			return;
		}
		long exp=n-m+1;
		mat=exp(mat,exp,MOD);
		long[][] res=mult(mat,start,MOD);
		System.out.println(res[0][0]%MOD);
	}
	public static long[][] identity() {
		long[][] a=new long[m][m];
		for(int i=0;i<m;i++) a[i][i]=1;
		return a;
	}
	public static long[][] exp(long[][] mat, long e, long m) {
		if(e==0) return identity();
		if(e%2==0) {
			long[][] temp=mult(mat,mat,MOD);
			return exp(temp,e/2,MOD);
		}
		return mult(mat,exp(mat,e-1,m),MOD);
	}
	public static long[][] mult(long[][] a, long[][] b, long moood) {
		long[][] c=new long[a.length][b[0].length];
		for(int i=0;i<a.length;i++) {
			for(int j=0;j<b[0].length;j++) {
				for(int k=0;k<a[0].length;k++) {
					c[i][j]=(c[i][j]+a[i][k]*b[k][j])%moood;
				}
			}
		}
		return c;
	}
	static int m;
	static final int MOD=(int)1e9+7;
	static long[] dp;
	public static long go(int x) {
		if(x==0) return dp[x]=1L;
		if(x<0) return 0L;
		if(dp[x]!=-1) return dp[x];
		long res=0L;
		res=(res+go(x-1)%MOD)%MOD;
		res=(res+go(x-m)%MOD)%MOD;
		return dp[x]=res;
	}
}

import java.util.*;
import java.io.*;
public class EdB {
	static long[] mods = {1000000007, 998244353, 1000000009};
	static long mod = mods[0];
	public static MyScanner sc;
    public static PrintWriter out;
    static long[][] matrix;
    static int m;
	public static void main(String[] omkar) throws Exception{
		// TODO Auto-generated method stub
 		sc = new MyScanner();
 		PrintWriter out = new PrintWriter(System.out);
 		long n = sc.nextLong();
 		m = sc.nextInt();
 		matrix = new long[m][m];
 		matrix[0][0] = 1;
 		matrix[0][m-1] = 1;
 		for(int j =1;j<m;j++){
 			matrix[j][j-1] = 1;
 		}
 		long[][] newm = new long[m][m];
 		if (n >= m)
 			newm = power(matrix, n-(long)m);
 		long ans = 0;
 		for(int j = 0;j<m;j++){
 			ans+=newm[0][j]*(j == 0 ? 2L : 1L);
 			ans%=mod;
 		}
 		out.println( (n < m ? 1 : ans));

 		out.close();
 	}
	public static long[][] mul(long[][] m1, long[][] m2){
		long[][] ans = new long[m][m];
		for(int j =0;j<m;j++){
			for(int k = 0;k<m;k++){
				long sum = 0;
				for(int l = 0;l<m;l++){
					sum+=m1[j][l]*m2[l][k];
					sum%=mod;
				}
				ans[j][k] = sum;
			}
		}
		return ans;
	}
	public static long[][] power(long[][] m1, long k){

		if (k == 0){
			long[][] mst = new long[m][m];
			for(int j =0 ;j<m;j++){
				mst[j][j] = 1L;
			}
			return mst;
		}

		if (k == 1)
			return m1;
		long [][]ks = power(m1, k/2L);
		if (k%2 == 0)
			return mul(ks, ks);
		else
			return mul(mul(ks, ks), m1);
	}
	public static void sort(int[] array){
		ArrayList<Integer> copy = new ArrayList<Integer>();
		for (int i : array)
			copy.add(i);
		Collections.sort(copy);
		for(int i = 0;i<array.length;i++)
			array[i] = copy.get(i);
	}
	static String[] readArrayString(int n){
		String[] array = new String[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.next();
		return array;
	}
	static int[] readArrayInt(int n){
    	int[] array = new int[n];
    	for(int j = 0;j<n;j++)
    		array[j] = sc.nextInt();
    	return array;
    }
	static int[] readArrayInt1(int n){
		int[] array = new int[n+1];
		for(int j = 1;j<=n;j++){
			array[j] = sc.nextInt();
		}
		return array;
	}
	static long[] readArrayLong(int n){
		long[] array = new long[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextLong();
		return array;
	}
	static double[] readArrayDouble(int n){
		double[] array = new double[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextDouble();
		return array;
	}
	static int minIndex(int[] array){
		int minValue = Integer.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(long[] array){
		long minValue = Long.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(double[] array){
		double minValue = Double.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static long power(long x, long y){
		if (y == 0)
			return 1;
		if (y%2 == 1)
			return (x*power(x, y-1))%mod;
		return power((x*x)%mod, y/2)%mod;
	}
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String nextLine() {
            String str = "";
            try{
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is

import java.util.*;
import java.io.*;
public class EdB {
	static long[] mods = {1000000007, 998244353, 1000000009};
	static long mod = mods[0];
	public static MyScanner sc;
    public static PrintWriter out;
    static long[][] matrix;
    static int m;
	public static void main(String[] omkar) throws Exception{
		// TODO Auto-generated method stub
 		sc = new MyScanner();
 		PrintWriter out = new PrintWriter(System.out);
 		long n = sc.nextLong();
 		m = sc.nextInt();
 		matrix = new long[m][m];
 		matrix[0][0] = 1;
 		matrix[0][m-1] = 1;
 		for(int j =1;j<m;j++){
 			matrix[j][j-1] = 1;
 		}
 		long[][] newm = new long[m][m];
 		if (n >= m)
 			newm = power(matrix, n-(long)m);
 		long ans = 0;
 		for(int j = 0;j<m;j++){
 			ans+=newm[0][j]*(j == 0 ? 2L : 1L);
 			ans%=mod;
 		}
 		out.println( (n < m ? 1 : ans));

 		out.close();
 	}
	public static long[][] mul(long[][] m1, long[][] m2){
		long[][] ans = new long[m][m];
		for(int j =0;j<m;j++){
			for(int k = 0;k<m;k++){
				for(int l = 0;l<m;l++){
					ans[j][l]+=m1[j][k]*m2[k][l];
					ans[j][l]%=mod;
				}
			}
		}
		return ans;
	}
	public static long[][] power(long[][] m1, long k){

		if (k == 0){
			long[][] mst = new long[m][m];
			for(int j =0 ;j<m;j++){
				mst[j][j] = 1L;
			}
			return mst;
		}

		if (k == 1)
			return m1;
		long [][]ks = power(m1, k/2L);
		if (k%2 == 0)
			return mul(ks, ks);
		else
			return mul(mul(ks, ks), m1);
	}
	public static void sort(int[] array){
		ArrayList<Integer> copy = new ArrayList<Integer>();
		for (int i : array)
			copy.add(i);
		Collections.sort(copy);
		for(int i = 0;i<array.length;i++)
			array[i] = copy.get(i);
	}
	static String[] readArrayString(int n){
		String[] array = new String[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.next();
		return array;
	}
	static int[] readArrayInt(int n){
    	int[] array = new int[n];
    	for(int j = 0;j<n;j++)
    		array[j] = sc.nextInt();
    	return array;
    }
	static int[] readArrayInt1(int n){
		int[] array = new int[n+1];
		for(int j = 1;j<=n;j++){
			array[j] = sc.nextInt();
		}
		return array;
	}
	static long[] readArrayLong(int n){
		long[] array = new long[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextLong();
		return array;
	}
	static double[] readArrayDouble(int n){
		double[] array = new double[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextDouble();
		return array;
	}
	static int minIndex(int[] array){
		int minValue = Integer.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(long[] array){
		long minValue = Long.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(double[] array){
		double minValue = Double.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static long power(long x, long y){
		if (y == 0)
			return 1;
		if (y%2 == 1)
			return (x*power(x, y-1))%mod;
		return power((x*x)%mod, y/2)%mod;
	}
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String nextLine() {
            String str = "";
            try{
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is

import java.util.*;
import java.io.*;

public class MagicGems {
    public static final long MOD = 1000000007L;
    public static final long MODS = MOD*MOD;
    public static void main(String[] args) {
        FastScanner scanner = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);
        long N = scanner.nextLong();
        int M = scanner.nextInt();
        long[][] matrix = new long[M][M];
        for(int i= 0; i  < M-1; i++) {
            matrix[i+1][i] = 1;
        }
        //base cases
        matrix[0][0] = 1;
        matrix[0][M-1] = 1;
        long[] ans = new long[M];
        ans[0] = 1;
        out.println(mPow(matrix, ans, N)[0]);
        out.flush();
    }

    //calculates the power and gets answer from it
    public static long[] mPow (long[][] M,  long[] v, long pow) {
        for(int i= 0; i < v.length; i++) if(v[i] >= MOD) v[i]%=MOD;
        long[][] ret = M;
        //>>>= is an unsigned right shift by 1
        for(;pow> 0; pow >>>=1) {
            if ((pow&1)==1) v = mMul(ret, v);
            ret = mSquare(ret);
        }
        return v;
    }

    public static long[] mMul(long[][] M, long[] v) {
        int m = M.length;
        int n= v.length;
        long[] ret = new long[m];
        for(int i= 0; i < m; i++) {
            long sum = 0;
            for(int k = 0; k < n; k++) {
                sum += M[i][k] * v[k];
                if (sum >= MODS) sum-= MODS;
            }
            ret[i] = sum%MOD;
        }
        return ret;
    }

    //need to be a square matrix
    //should have efficiency based on lacking mod ops.
    public static long[][] mSquare(long[][] M) {
        int N = M.length;
        long[][] ret = new long[N][N];
        for(int i = 0; i < N; i++) {
            long[] temp = new long[N];
            for(int k = 0; k < N; k++) {
                for(int j = 0; j < N; j++) {
                    temp[j] += M[i][k] * M[k][j];
                    if (temp[j] >= MODS) temp[j]-=MODS;
                }
            }
            for(int k = 0; k < N; k++) {
                ret[i][k] = (temp[k] %MOD);
            }
        }
        return ret;
    }

    public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(Reader in) {
            br = new BufferedReader(in);
        }

        public FastScanner() {
            this(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String readNextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        int[] readIntArray(int n) {
            int[] a = new int[n];
            for (int idx = 0; idx < n; idx++) {
                a[idx] = nextInt();
            }
            return a;
        }
    }
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class Solution {

	public static void main(String[] args) {
		InputReader in = new InputReader();
		PrintWriter out = new PrintWriter(System.out);
		Thread th = new Thread(null, new Runnable(){public void run(){new Task1().solve(in, out);}},"Task1",1<<24);
		try{
			th.start();
			th.join();
		} catch(InterruptedException e){}
		out.close();
	}

	static class Task1 {
		static final int MOD = 1000000007;
		static final int MAX = 1000002;
		static final boolean DEBUG = false;

		public void solve(InputReader in, PrintWriter out){
			long n = in.nextLong();
			int m = in.nextInt();
			long[][] T = new long[m][m];	// transformation matrix
			for(int i=0; i<m-1; i++){
				T[i][i+1] = 1;
			}
			T[m-1][0] = T[m-1][m-1] = 1;

			if(DEBUG){
				for(long[] x:T){
					for(long y:x){
						out.print(y+" ");
					}
					out.println();
				}
			}

			// Recurrence for this problem : dp[n] = dp[n-1] + 0 + 0 +.. + dp[n-m]
			// Fn = matrixExponentiation(T, n-1) * F1
			long[][] f1 = new long[m][1];	// column matrix
			for(int i=0; i<m; i++){
				f1[i][0] = 1;
			}
			f1[m-1][0] = 2;

			long[][] ans = multiplyMatrix(matrixExponent(T, n-1), f1);
			if(DEBUG){
				for(long[] x:ans){
					for(long y:x){
						out.print((y)+" ");
					}
					out.println();
				}
			}
			out.println(ans[0][0]%MOD);
		}

		static long[][] matrixExponent(long[][] T, long n) {
			assert(T.length == T[0].length);
			long result[][] = new long[T.length][T.length];
			long[][] temp = new long[T.length][T.length];
			for(int i=0; i<T.length; i++){
				for(int j=0; j<T.length; j++){
					temp[i][j] = T[i][j];
				}
				result[i][i] = 1;
			}
			while(n>0){
				if(n%2==1) result = multiplyMatrix(result, temp);
				n>>=1;
				temp = multiplyMatrix(temp, temp);
			}
			return result;
		}

		static long[][] multiplyMatrix(long[][] a, long[][] b){
			assert(a[0].length == b.length);
			long[][] ans = new long[a.length][b[0].length];
			for(int i=0; i<a.length; i++){
				for(int j=0; j<b[0].length; j++){
					for(int k=0; k<a[0].length; k++){
						ans[i][j] = (ans[i][j] + (a[i][k]*b[k][j])%MOD)%MOD;
					}
				}
			}
			return ans;
		}

		/*private static long[][] multiplyMatrix(long[][] T, long[][] f1) {
			long ans[][] = new long[T.length][f1[0].length];
			for (int i = 0; i < T.length; i++) {
				for (int j = 0; j < f1[0].length; j++) {
					ans[i][j] = 0;
					for (int k = 0; k < f1.length; k++) {
					    ans[i][j] = (MOD + ans[i][j] + (T[i][k] * f1[k][j])) % MOD;
					}
				}
			}
			return ans;
		}*/

	}

	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;
		public InputReader() {
			reader = new BufferedReader(new InputStreamReader(System.in));
			tokenizer = null;
		}
		public String next() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
			return tokenizer.nextToken();
		}
		public int nextInt() {
			return Integer.parseInt(next());
		}
		public long nextLong() {
			return Long.parseLong(next());
		}
		public double nextDouble() {
			return Double.parseDouble(next());
		}
		public String nextLine() {
			String s=null;
			try{
				s = reader.readLine();
			} catch(IOException e){
				throw new RuntimeException(e);
			}
			return s;
		}
		public String nextParagraph() {
			String line=null;
			String ans = "";
			try{
				while ((line = reader.readLine()) != null) {
				ans += line+"\n";
				}
			} catch(IOException e){
				throw new RuntimeException(e);
			}
			return ans;
		}
	}
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        long MOD = (long) (1e9 + 7);

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long N = in.nextLong();
            int M = in.nextInt();
            long[][] m = new long[M][M];
            long[][] res = new long[M][1];
            m[0][0] = 1;
            m[0][M - 1] = 1;
            res[0][0] = 1;
            for (int i = 1; i < M; i++) {
                m[i][i - 1] = 1;
            }
            MathUtils.Matrix transition = new MathUtils.Matrix(m);
            MathUtils.Matrix end = new MathUtils.Matrix(res);
            end.multiply(transition.pow(N, MOD), MOD);
            out.println(end.m[0][0]);
        }

    }

    static class MathUtils {
        public static class Matrix {
            public long[][] m;
            int rows;
            int cols;

            public Matrix(long[][] m) {
                rows = m.length;
                cols = m[0].length;
                this.m = m;
            }

            public Matrix(int r, int c) {
                m = new long[r][c];
                rows = r;
                cols = c;
            }

            public MathUtils.Matrix getIdentity() {
                assert rows == cols : "Matrix is not square, no identity possible";
                long[][] identity = new long[rows][cols];
                for (int i = 0; i < rows; i++) {
                    identity[i][i] = 1;
                }
                return new MathUtils.Matrix(identity);
            }

            public static MathUtils.Matrix multiply(MathUtils.Matrix a, MathUtils.Matrix b, long mod) {
                //does not change in place
                assert a.cols == b.rows : "Input mismatch, rows do not match columns";
                long[][] newMatrix = new long[a.rows][b.cols];
                for (int i = 0; i < a.rows; i++) {
                    for (int k = 0; k < a.cols; k++) {
                        for (int j = 0; j < b.cols; j++) {
                            newMatrix[i][j] += (a.m[i][k] * b.m[k][j]) % mod;
                            newMatrix[i][j] %= mod;
                        }
                    }
                }
                return new MathUtils.Matrix(newMatrix);
            }

            public void multiply(MathUtils.Matrix b, long mod) {
                //changes in place
                assert cols == b.rows : "Input mismatch, rows do not match columns";
                long[][] newMatrix = new long[rows][b.cols];
                for (int i = 0; i < rows; i++) {
                    for (int k = 0; k < cols; k++) {
                        for (int j = 0; j < b.cols; j++) {
                            newMatrix[i][j] += (this.m[i][k] * b.m[k][j]) % mod;
                            newMatrix[i][j] %= mod;
                        }
                    }
                }
                m = newMatrix;
            }

            public MathUtils.Matrix pow(long n, long mod) {
                //does not change in place
                assert rows == cols : "Matrix is not square";
                MathUtils.Matrix res = this.getIdentity();
                MathUtils.Matrix base = new MathUtils.Matrix(this.m);
                while (n > 0) {
                    if ((n & 1) == 1) {
                        res.multiply(base, mod);
                    }
                    base = MathUtils.Matrix.multiply(base, base, mod);
                    n = n >> 1;
                }
                return res;
            }

        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }
}

import java.util.*;

public class Main {
static int mod = 1_000_000_007;
static long[][] mul(long[][] A, long[][] B) {
    long[][] C = new long[A.length][B[0].length];
    for (int i=0;i<A.length;i++) {
        for (int k=0;k<B.length;k++) {
            for (int j=0;j<B[0].length;j++) {
                C[i][j] = (C[i][j]+A[i][k]*B[k][j])%mod;
            }
        }
    }
    return C;
}

static long[][] pow(long[][] A, long n) {
    long[][] B = new long[A.length][A.length];
    for (int i=0;i<A.length;i++) {
        B[i][i]=1;
    }
    while (n>0) {
        if ((n&1)==1) {
            B = mul(B, A);
        }
        A = mul(A, A);
        n>>=1;
    }
    return B;
}

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long N = sc.nextLong();
        int M = sc.nextInt();
        long[][] matrix = new long[M][M];
        matrix[0][0] = 1;
        matrix[0][M-1] = 1;
        for (int i=1;i<M;i++) {
            matrix[i][i-1] = 1;
        }

        if (N<M) {
            System.out.println(1);
            return;
        }
        long[][] ans = pow(matrix, N-M+1);
        // System.out.println(Arrays.deepToString(matrix));
        long[][] arr = new long[M][1];
        for (int i=0;i<M;i++) {
            arr[i][0] = 1;
        }
        ans = mul(ans, arr);
        // System.out.println(Arrays.deepToString(ans));
        System.out.println(ans[0][0]);
    }
}

import java.util.Scanner;

public class D
{
	static int mod = 1000000007;
	public static void main(String[] args)
	{
		Scanner scan = new Scanner(System.in);
		long n = scan.nextLong();
		int m = scan.nextInt();
		int[][] matrix = new int[m][m];
		matrix[0][0] = 1;
		matrix[m-1][0] = 1;
		for (int i = 1; i < m; i++)
			matrix[i-1][i] = 1;
		int[][] res = fastExpo(matrix, n);
		int[][] init = new int[1][m];
		init[0][0] = 1;
		System.out.println(mult(init, res)[0][0]);
	}

	private static int[][] fastExpo(int[][] matrix, long p)
	{
		if (p == 1)
			return matrix;
		if (p % 2 == 1)
			return mult(matrix, fastExpo(matrix, p-1));
		int[][] half = fastExpo(matrix, p/2);
		return mult(half, half);
	}

	private static int[][] mult(int[][] a, int[][] b)
	{
		int[][] res = new int[a.length][b[0].length];
		for (int i = 0; i < res.length; i++)
		{
			for (int j = 0; j < res[0].length; j++)
			{
				long s = 0;
				for (int k = 0; k < b.length; k++)
				{
					s += (long)a[i][k]*b[k][j];
					s %= mod;
				}
				res[i][j] = (int)(s % mod);
			}
		}
		return res;
	}
}

import java.util.*;

public class Dcode {

    static  int m;
    static  int mod = 1000000007;

    static  long[][] mul(long a[][],long n){
        if(n<=1){
            return a;
        }

        long matrix[][] = new long[m][m];
        for(int i=0;i<m;i++){
            matrix[i][i] = 1;

        }

        while(n>0){
                if((n&1) == 1){
                        matrix = mm(matrix,a);

                }

                    a = mm(a,a);

                        n = n>>1;
        }

         return matrix;

    }

    static long[][] mm(long a[][],long b[][]){
        long c[][] = new long[m][m];

        for(int i=0;i<m;i++){
            for(int j=0;j<m;j++){
                long sum = 0;
                for(int k=0;k<m;k++){
                    sum = (sum + a[i][k]*b[k][j])%mod;
                }

                c[i][j] = sum;
            }
        }

        return c;
    }

    public static  void main(String args[]){

        Scanner s = new Scanner(System.in);
        long n = s.nextLong();
        m = s.nextInt();
        if(n<m){
            System.out.println(1);
            return;
        }
        if(n==m){
            System.out.println(2);
            return;
        }
        long a[][] = new long[m][m];

        a[0][0] = 1;
        a[0][m-1] = 1;
        for(int i=1;i<m;i++){
            a[i][i-1] = 1;
        }

        long ans  = 0;

        long h[][] = mul(a,n-m);

        ans = 2*h[0][0];

        for(int i=1;i<m;i++){
            ans = (ans + h[0][i])%mod;
        }

        System.out.println(ans);

    }
}

import java.util.*;

public class D {

    public static final int MOD = 1000000007;
    public static long[][] multiply_matrix = new long[103][103];

    public static void matrix_multiplication(int m, long[][] final_matrix, long[][] multiply_matrix){
        long[][] mult = new long[m][m];

        for(int i=0; i<m; i++){
            for(int j=0; j<m; j++){
                mult[i][j] = 0;
                for(int k=0; k<m; k++){
                    mult[i][j] += final_matrix[i][k] * multiply_matrix[k][j];
                    if(mult[i][j] > MOD){
                        mult[i][j] %= MOD;
                    }
                }
            }
        }
        for(int i=0; i<m; i++){
            for(int j=0; j<m; j++){
                final_matrix[i][j] = mult[i][j];
            }
        }
    }

    public static void matrix_power(long n, long[][] final_matrix, int m){
        long[][] ans = new long[m][100];
        long[][] b = new long[m][100];

        for(int i=0; i<m; i++){
            for(int j=0; j<m; j++){
                ans[i][j] = multiply_matrix[i][j];
                b[i][j] = multiply_matrix[i][j];
            }
        }
        n--;
        while (n > 0){
            if(n % 2 == 1){
                matrix_multiplication(m, ans, b);
                n--;
            }
            else{
                matrix_multiplication(m, b, b);
                n /= 2;
            }
        }
        for(int i=0; i<m; i++){
            for(int j=0; j<m; j++){
                final_matrix[i][j] = ans[i][j];
            }
        }
    }
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        long n = scan.nextLong();
        int m = scan.nextInt();

        scan.close();

        for(int i=0; i<m; i++){
            for(int j=0; j<m; j++){
                multiply_matrix[i][j] = 0;
            }
        }

        multiply_matrix[0][0] = 1;
        multiply_matrix[0][m-1] = 1;
        for(int i=1; i<m; i++){
            multiply_matrix[i][i-1] = 1;
        }
        if(n < m){
            System.out.println(1);
        }
        else {
            long[][] final_matrix = new long[m+1][100];
            matrix_power(n-m+1, final_matrix, m);
            long ans = 0;
            for(int i=0; i<m; i++){
                ans += final_matrix[0][i];
                if (ans >= MOD){
                    ans -= MOD;
                }
            }
            System.out.println(ans);
        }
    }
}

import java.util.*;
import java.io.*;
public class HelloWorld{

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;
        public Scanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

        public Scanner(FileReader fileReader) {
            br = new BufferedReader(fileReader);
        }

        public String next() throws IOException {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public String nextLine() throws IOException {
            return br.readLine();
        }

        public boolean ready() throws IOException {
            return br.ready();
        }
    }

    static long mod=(long)1e9+7;
    static long[][] I;

     public static void main (String []args) throws IOException {
         Scanner sc = new Scanner(System.in);
         long n = sc.nextLong();int m = sc.nextInt();
         I=new long[m][m];
         long[][] M = new long[m][m];
         for(int i=1;i<m;i++){
             I[i][i] = M[i-1][i] = 1L;

         }
         I[0][0] = M[0][0]=M[m-1][0]=1L;

         M=exp(M,n);
         System.out.print(M[0][0]);
    }
    public static long[][] exp(long[][] M,long n){
        long[][] res = I;
        if(n==0) return I;
        if(n==1) return M;
        while(n>0){
        if(n%2!=0)res=mult(res,M);
        n/=2;
        M=mult(M,M);
        }
        return res;
    }
    public static long[][] mult(long[][]p ,long[][] q){
        long[][] r = new long[p.length][q[0].length];
        for(int i=0;i<p.length;i++){
            for(int j=0;j<q[0].length;j++){
                for(int k=0;k<q.length;k++){
                    r[i][j]+=p[i][k]*q[k][j];
                    r[i][j]%=mod;
                }
            }
        }
        return r;
    }
}

import java.io.*;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

public class Main {
    public static void main(String[] args) throws FileNotFoundException {
        ConsoleIO io = new ConsoleIO(new InputStreamReader(System.in), new PrintWriter(System.out));

//        String fileName = "C-large-practice";
//        ConsoleIO io = new ConsoleIO(new FileReader("D:\\Dropbox\\code\\practice\\jb\\src\\" + fileName + ".in"), new PrintWriter(new File("D:\\Dropbox\\code\\practice\\jb\\src\\" + fileName + ".out")));

        new Main(io).solve();
//        new Main(io).solveLocal();

        io.close();
    }

    ConsoleIO io;

    Main(ConsoleIO io) {
        this.io = io;
    }

    ConsoleIO opt;

    Main(ConsoleIO io, ConsoleIO opt) {
        this.io = io;
        this.opt = opt;
    }

    List<List<Integer>> gr = new ArrayList<>();

    long MOD = 1_000_000_007;

    long n,m;
    public void solve() {
        long[] l = io.readLongArray();
        n = l[0];
        m = l[1];
        memo = new HashMap<>();
        long res = calc(n);
        io.writeLine(res + "");
    }

    HashMap<Long, Long> memo;

    long calc(long v) {
        if (v < m) {
            return 1;
        }
        Long res = memo.get(v);
        if(res != null){
            return res;
        }

        long c1 = v / 2;
        long c2 = v - c1;
        long t = calc(c1) * calc(c2) % MOD;
        for (long h = Math.max(1, m - c2); h < m && h <= c1; h++) {
            t += calc(c1 - h) * calc(c2 - m + h) % MOD;
        }

        res = t % MOD;
        memo.put(v, res);
        return res;
    }
}

class ConsoleIO {

    BufferedReader br;
    PrintWriter out;
    public ConsoleIO(Reader reader, PrintWriter writer){br = new BufferedReader(reader);out = writer;}
    public void flush(){this.out.flush();}
    public void close(){this.out.close();}
    public void writeLine(String s) {this.out.println(s);}
    public void writeInt(int a) {this.out.print(a);this.out.print(' ');}
    public void writeWord(String s){
        this.out.print(s);
    }
    public void writeIntArray(int[] a, int k, String separator) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < k; i++) {
            if (i > 0) sb.append(separator);
            sb.append(a[i]);
        }
        this.writeLine(sb.toString());
    }
    public void writeLongArray(long[] a, int k, String separator) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < k; i++) {
            if (i > 0) sb.append(separator);
            sb.append(a[i]);
        }
        this.writeLine(sb.toString());
    }
    public int read(char[] buf, int len){try {return br.read(buf,0,len);}catch (Exception ex){ return -1; }}
    public String readLine() {try {return br.readLine();}catch (Exception ex){ return "";}}
    public long[] readLongArray() {
        String[]n=this.readLine().trim().split("\\s+");long[]r=new long[n.length];
        for(int i=0;i<n.length;i++)r[i]=Long.parseLong(n[i]);
        return r;
    }
    public int[] readIntArray() {
        String[]n=this.readLine().trim().split("\\s+");int[]r=new int[n.length];
        for(int i=0;i<n.length;i++)r[i]=Integer.parseInt(n[i]);
        return r;
    }
    public int[] readIntArray(int n) {
        int[] res = new int[n];
        char[] all = this.readLine().toCharArray();
        int cur = 0;boolean have = false;
        int k = 0;
        boolean neg = false;
        for(int i = 0;i<all.length;i++){
            if(all[i]>='0' && all[i]<='9'){
                cur = cur*10+all[i]-'0';
                have = true;
            }else if(all[i]=='-') {
                neg = true;
            }
            else if(have){
                res[k++] = neg?-cur:cur;
                cur = 0;
                have = false;
                neg = false;
            }
        }
        if(have)res[k++] = neg?-cur:cur;
        return res;
    }
    public int ri() {
        try {
            int r = 0;
            boolean start = false;
            boolean neg = false;
            while (true) {
                int c = br.read();
                if (c >= '0' && c <= '9') {
                    r = r * 10 + c - '0';
                    start = true;
                } else if (!start && c == '-') {
                    start = true;
                    neg = true;
                } else if (start || c == -1) return neg ? -r : r;
            }
        } catch (Exception ex) {
            return -1;
        }
    }
    public long readLong() {
        try {
            long r = 0;
            boolean start = false;
            boolean neg = false;
            while (true) {
                int c = br.read();
                if (c >= '0' && c <= '9') {
                    r = r * 10 + c - '0';
                    start = true;
                } else if (!start && c == '-') {
                    start = true;
                    neg = true;
                } else if (start || c == -1) return neg ? -r : r;
            }
        } catch (Exception ex) {
            return -1;
        }
    }
    public String readWord() {
        try {
            boolean start = false;
            StringBuilder sb = new StringBuilder();
            while (true) {
                int c = br.read();
                if (c!= ' ' && c!= '\r' && c!='\n' && c!='\t') {
                    sb.append((char)c);
                    start = true;
                } else if (start || c == -1) return sb.toString();
            }
        } catch (Exception ex) {
            return "";
        }
    }
    public char readSymbol() {
        try {
            while (true) {
                int c = br.read();
                if (c != ' ' && c != '\r' && c != '\n' && c != '\t') {
                    return (char) c;
                }
            }
        } catch (Exception ex) {
            return 0;
        }
    }
//public char readChar(){try {return (char)br.read();}catch (Exception ex){ return 0; }}
}
class Pair {
    public Pair(int a, int b) {this.a = a;this.b = b;}
    public int a;
    public int b;
}
class PairLL {
    public PairLL(long a, long b) {this.a = a;this.b = b;}
    public long a;
    public long b;
}
class Triple {
    public Triple(int a, int b, int c) {this.a = a;this.b = b;this.c = c;}
    public int a;
    public int b;
    public int c;
}

import java.io.*;
import java.util.*;

public class tr7 {

	static int[][] matMult(int[][] A, int[][] B) {
		int p = A.length, q = A[0].length, r = B[0].length;
		int[][] ans = new int[p][r];
		for (int i = 0; i < p; i++)
			for (int k = 0; k < q; k++)
				for (int j = 0; j < r; j++)
				{
					ans[i][j] += A[i][k] * 1L * B[k][j] % MOD;
					if (ans[i][j] >= MOD)
						ans[i][j] -= MOD;
				}
		return ans;
	}

	static int[][] pow(int[][] A, long e) {
		int n = A.length;
		int[][] ans = new int[n][n];
		for (int i = 0; i < n; i++)
			ans[i][i] = 1;
		while (e > 0) {
			if ((e & 1) == 1) {
				ans = matMult(ans, A);
			}
			e >>= 1;
			A = matMult(A, A);
		}
		return ans;
	}

	static int MOD = (int) 1e9 + 7;

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		long n = sc.nextLong();
		int m = sc.nextInt();
		if (m > n) {
			System.out.println(1);
			return;
		}
		int[][] A = new int[m][m];
		A[0][0] = A[0][m - 1] = 1;
		for (int i = 1; i < m; i++)
			A[i][i - 1] = 1;
		out.println(pow(A, n)[0][0]);

		out.close();
	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}
	}
}

//created by Whiplash99
import java.io.*;
import java.util.*;
public class F
{
    private static final long MOD=(long)(1e9+7);
    static class Matrix
    {
        long[][] M; int N;
        Matrix(int N){this.N=N; M=new long[N][N];}
        void makeIdentity(){for(int i=0;i<N;i++) M[i][i]=1;}
        void copy(Matrix source)
        {
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    M[i][j]=source.M[i][j];
        }
        void multiply(Matrix B, Matrix C)
        {
            for(int i=0;i<N;i++) Arrays.fill(C.M[i],0);
            for(int i=0;i<N;i++)
                for(int k=0;k<N;k++)
                    for(int j=0;j<N;j++)
                        C.M[i][j]=(C.M[i][j]+M[i][k]*B.M[k][j]%MOD)%MOD;
            copy(C);
        }
        void pow(long b)
        {
            Matrix res=new Matrix(N), store=new Matrix(N);
            res.makeIdentity();
            while (b>0)
            {
                if((b&1)==1) res.multiply(this,store);
                this.multiply(this,store);
                b>>=1;
            }
            copy(res);
        }
    }
    public static void main(String[] args) throws IOException
    {
        Reader r=new Reader();

        int i,j;

        long N=r.nextLong();
        int M=r.nextInt();

        if(N<M){ System.out.println(1); System.exit(0);}

        Matrix A=new Matrix(M);
        Matrix P=new Matrix(M);
        Matrix store=new Matrix(M);

        Arrays.fill(A.M[0],1); A.M[0][M-1]=2;
        for(i=1;i<M;i++) P.M[i][i-1]=1; P.M[0][M-1]=P.M[M-1][M-1]=1;

        P.pow(N-M);
        A.multiply(P,store);

        System.out.println(A.M[0][M-1]);
    }
    static class Reader
    {
        final private int BUFFER_SIZE = 1 << 16;private DataInputStream din;private byte[] buffer;private int bufferPointer, bytesRead;
        public Reader(){din=new DataInputStream(System.in);buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public Reader(String file_name) throws IOException{din=new DataInputStream(new FileInputStream(file_name));buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public String readLine() throws IOException{byte[] buf=new byte[64];int cnt=0,c;while((c=read())!=-1){if(c=='\n')break;buf[cnt++]=(byte)c;}return new String(buf,0,cnt);
        }public int nextInt() throws IOException{int ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
        }public long nextLong() throws IOException{long ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
        }public double nextDouble() throws IOException{double ret=0,div=1;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c = read();do {ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(c=='.')while((c=read())>='0'&&c<='9')ret+=(c-'0')/(div*=10);if(neg)return -ret;return ret;
        }private void fillBuffer() throws IOException{bytesRead=din.read(buffer,bufferPointer=0,BUFFER_SIZE);if(bytesRead==-1)buffer[0]=-1;
        }private byte read() throws IOException{if(bufferPointer==bytesRead)fillBuffer();return buffer[bufferPointer++];
        }public void close() throws IOException{if(din==null) return;din.close();}
    }
}

//created by Whiplash99
import java.io.*;
import java.util.*;
public class F
{
    private static final long MOD=(long)(1e9+7);
    static class Matrix
    {
        long[][] M; int N;
        Matrix(int N){this.N=N; M=new long[N][N];}
        void makeIdentity(){for(int i=0;i<N;i++) M[i][i]=1;}
        void copy(Matrix source)
        {
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    M[i][j]=source.M[i][j];
        }
        void multiply(Matrix B, Matrix C)
        {
            for(int i=0;i<N;i++) Arrays.fill(C.M[i],0);
            for(int i=0;i<N;i++)
                for(int k=0;k<N;k++)
                    for(int j=0;j<N;j++)
                        C.M[i][j]=add(C.M[i][j],prod(M[i][k],B.M[k][j]));
            copy(C);
        }
        void pow(long b)
        {
            Matrix res=new Matrix(N), store=new Matrix(N);
            res.makeIdentity();
            while (b>0)
            {
                if((b&1)==1) res.multiply(this,store);
                this.multiply(this,store);
                b>>=1;
            }
            copy(res);
        }
    }
    private static long add(long a, long b){a+=b; return (a>=MOD)?a-MOD:a;}
    private static long prod(long a, long b){a*=b; return (a>=MOD)?a%MOD:a;}
    public static void main(String[] args) throws IOException
    {
        Reader r=new Reader();

        int i,j;

        long N=r.nextLong();
        int M=r.nextInt();

        if(N<M){ System.out.println(1); System.exit(0);}

        Matrix A=new Matrix(M);
        Matrix P=new Matrix(M);
        Matrix store=new Matrix(M);

        Arrays.fill(A.M[0],1); A.M[0][M-1]=2;
        for(i=1;i<M;i++) P.M[i][i-1]=1; P.M[0][M-1]=P.M[M-1][M-1]=1;

        P.pow(N-M);
        A.multiply(P,store);

        System.out.println(A.M[0][M-1]);
    }
    static class Reader
    {
        final private int BUFFER_SIZE = 1 << 16;private DataInputStream din;private byte[] buffer;private int bufferPointer, bytesRead;
        public Reader(){din=new DataInputStream(System.in);buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public Reader(String file_name) throws IOException{din=new DataInputStream(new FileInputStream(file_name));buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public String readLine() throws IOException{byte[] buf=new byte[64];int cnt=0,c;while((c=read())!=-1){if(c=='\n')break;buf[cnt++]=(byte)c;}return new String(buf,0,cnt);
        }public int nextInt() throws IOException{int ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
        }public long nextLong() throws IOException{long ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
        }public double nextDouble() throws IOException{double ret=0,div=1;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c = read();do {ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(c=='.')while((c=read())>='0'&&c<='9')ret+=(c-'0')/(div*=10);if(neg)return -ret;return ret;
        }private void fillBuffer() throws IOException{bytesRead=din.read(buffer,bufferPointer=0,BUFFER_SIZE);if(bytesRead==-1)buffer[0]=-1;
        }private byte read() throws IOException{if(bufferPointer==bytesRead)fillBuffer();return buffer[bufferPointer++];
        }public void close() throws IOException{if(din==null) return;din.close();}
    }
}

//created by Whiplash99
import java.io.*;
import java.util.*;
public class F
{
    private static final long MOD=(long)(1e9+7);
    static class Matrix
    {
        long[][] M; int N;
        Matrix(int N){this.N=N; M=new long[N][N];}
        void makeIdentity(){for(int i=0;i<N;i++) M[i][i]=1;}
        void copy(Matrix source)
        {
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    M[i][j]=source.M[i][j];
        }
        void multiply(Matrix B, Matrix C)
        {
            for(int i=0;i<N;i++) Arrays.fill(C.M[i],0);
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    for(int k=0;k<N;k++)
                        C.M[i][j]=add(C.M[i][j],prod(M[i][k],B.M[k][j]));
            copy(C);
        }
        void pow(long b)
        {
            Matrix res=new Matrix(N), store=new Matrix(N);
            res.makeIdentity();
            while (b>0)
            {
                if((b&1)==1) res.multiply(this,store);
                this.multiply(this,store);
                b>>=1;
            }
            copy(res);
        }
    }
    private static long add(long a, long b){a+=b; return (a>=MOD)?a-MOD:a;}
    private static long prod(long a, long b){a*=b; return (a>=MOD)?a%MOD:a;}
    public static void main(String[] args) throws IOException
    {
        Reader r=new Reader();

        int i,j;

        long N=r.nextLong();
        int M=r.nextInt();

        if(N<M){ System.out.println(1); System.exit(0);}

        Matrix A=new Matrix(M);
        Matrix P=new Matrix(M);
        Matrix store=new Matrix(M);

        Arrays.fill(A.M[0],1); A.M[0][M-1]=2;
        for(i=1;i<M;i++) P.M[i][i-1]=1; P.M[0][M-1]=P.M[M-1][M-1]=1;

        P.pow(N-M);
        A.multiply(P,store);

        System.out.println(A.M[0][M-1]);
    }
    static class Reader
    {
        final private int BUFFER_SIZE = 1 << 16;private DataInputStream din;private byte[] buffer;private int bufferPointer, bytesRead;
        public Reader(){din=new DataInputStream(System.in);buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public Reader(String file_name) throws IOException{din=new DataInputStream(new FileInputStream(file_name));buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public String readLine() throws IOException{byte[] buf=new byte[64];int cnt=0,c;while((c=read())!=-1){if(c=='\n')break;buf[cnt++]=(byte)c;}return new String(buf,0,cnt);
        }public int nextInt() throws IOException{int ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
        }public long nextLong() throws IOException{long ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
        }public double nextDouble() throws IOException{double ret=0,div=1;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c = read();do {ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(c=='.')while((c=read())>='0'&&c<='9')ret+=(c-'0')/(div*=10);if(neg)return -ret;return ret;
        }private void fillBuffer() throws IOException{bytesRead=din.read(buffer,bufferPointer=0,BUFFER_SIZE);if(bytesRead==-1)buffer[0]=-1;
        }private byte read() throws IOException{if(bufferPointer==bytesRead)fillBuffer();return buffer[bufferPointer++];
        }public void close() throws IOException{if(din==null) return;din.close();}
    }
}

//created by Whiplash99
import java.io.*;
import java.util.*;
public class F
{
    private static final long MOD=(long)(1e9+7);
    static class Matrix
    {
        long[][] M; int N;
        Matrix(int N){this.N=N; M=new long[N][N];}
        void makeIdentity(){for(int i=0;i<N;i++) M[i][i]=1;}
        void copy(Matrix source)
        {
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    M[i][j]=source.M[i][j];
        }
        void multiply(Matrix B, Matrix C)
        {
            for(int i=0;i<N;i++) Arrays.fill(C.M[i],0);
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    for(int k=0;k<N;k++)
                        C.M[i][j]=(C.M[i][j]+M[i][k]*B.M[k][j]%MOD)%MOD;
            copy(C);
        }
        void pow(long b)
        {
            Matrix res=new Matrix(N), store=new Matrix(N);
            res.makeIdentity();
            while (b>0)
            {
                if((b&1)==1) res.multiply(this,store);
                this.multiply(this,store);
                b>>=1;
            }
            copy(res);
        }
    }
    public static void main(String[] args) throws IOException
    {
        Reader r=new Reader();

        int i,j;

        long N=r.nextLong();
        int M=r.nextInt();

        if(N<M){ System.out.println(1); System.exit(0);}

        Matrix A=new Matrix(M);
        Matrix P=new Matrix(M);
        Matrix store=new Matrix(M);

        Arrays.fill(A.M[0],1); A.M[0][M-1]=2;
        for(i=1;i<M;i++) P.M[i][i-1]=1; P.M[0][M-1]=P.M[M-1][M-1]=1;

        P.pow(N-M);
        A.multiply(P,store);

        System.out.println(A.M[0][M-1]);
    }
    static class Reader
    {
        final private int BUFFER_SIZE = 1 << 16;private DataInputStream din;private byte[] buffer;private int bufferPointer, bytesRead;
        public Reader(){din=new DataInputStream(System.in);buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public Reader(String file_name) throws IOException{din=new DataInputStream(new FileInputStream(file_name));buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public String readLine() throws IOException{byte[] buf=new byte[64];int cnt=0,c;while((c=read())!=-1){if(c=='\n')break;buf[cnt++]=(byte)c;}return new String(buf,0,cnt);
        }public int nextInt() throws IOException{int ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
        }public long nextLong() throws IOException{long ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
        }public double nextDouble() throws IOException{double ret=0,div=1;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c = read();do {ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(c=='.')while((c=read())>='0'&&c<='9')ret+=(c-'0')/(div*=10);if(neg)return -ret;return ret;
        }private void fillBuffer() throws IOException{bytesRead=din.read(buffer,bufferPointer=0,BUFFER_SIZE);if(bytesRead==-1)buffer[0]=-1;
        }private byte read() throws IOException{if(bufferPointer==bytesRead)fillBuffer();return buffer[bufferPointer++];
        }public void close() throws IOException{if(din==null) return;din.close();}
    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author beginner1010
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        final int mod = (int) 1e9 + 7;

        long[][] mul(long[][] A, long[][] B) {
            int a = A.length;
            int b = B.length;
            int c = B[0].length;
            long[][] C = new long[a][c];
            for (int i = 0; i < a; i++) {
                for (int k = 0; k < b; k++) {
                    for (int j = 0; j < c; j++) {
                        C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
                    }
                }
            }
            return C;
        }

        long[][] fastPow(long[][] graph, long p) {
            if (p == 0) {
                int n = graph.length;
                long[][] I = new long[n][n];
                for (int i = 0; i < n; i++) {
                    I[i][i] = 1;
                }
                return I;
            }
            if (p % 2 == 1) {
                return mul(graph, fastPow(graph, p - 1));
            } else {
                long[][] aux = fastPow(graph, p >> 1);
                return mul(aux, aux);
            }
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long N = in.nextLong();
            int M = in.nextInt();

            long[][] graph = new long[M][M];
            for (int i = 0; i < M - 1; i++) {
                graph[i][i + 1] = 1;
            }
            graph[M - 1][M - 1] = 1;
            graph[M - 1][0] = 1;

            long[][] ways = fastPow(graph, N);

            long[][] base = new long[M][1];
            base[M - 1][0] = 1;

            long[][] ans = mul(ways, base);

            out.println(ans[M - 1][0]);
        }

    }

    static class InputReader {
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputStream stream;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        private boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        private int read() {
            if (numChars == -1)
                throw new InputMismatchException();
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isWhitespace(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isWhitespace(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isWhitespace(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isWhitespace(c));
            return res * sgn;
        }

    }
}

//created by Whiplash99
import java.io.*;
import java.util.*;
public class D
{
    private static final long MOD=(long)(1e9+7);

    private static void makeIdentity(long[][] P, int M){for(int i=0;i<M;i++) P[i][i]=1;}
    private static void copy(long[][] source, long[][] dest, int M)
    {
        for (int i = 0; i < M; i++)
            for (int j = 0; j < M; j++)
                dest[i][j] = source[i][j];
    }
    private static void multiply(long[][] A, long[][] B, long[][] C, int M)
    {
        for (int i = 0; i < M; i++) Arrays.fill(C[i], 0);
        for (int i = 0; i < M; i++)
            for (int j = 0; j < M; j++)
                for (int k = 0; k < M; k++)
                    C[i][j] = add(C[i][j], prod(A[i][k], B[k][j]));
        copy(C, A, M);
    }
    private static void pow(long[][] P, int M, long b)
    {
        long[][] res = new long[M][M], store = new long[M][M];
        makeIdentity(res, M);
        while (b > 0)
        {
            if ((b & 1) == 1) multiply(res, P, store, M);
            multiply(P, P, store, M);
            b >>= 1;
        }
        copy(res, P, M);
    }

    private static long add(long a, long b){a+=b; return (a>=MOD)?a-MOD:a;}
    private static long prod(long a, long b){a*=b; return (a>=MOD)?a%MOD:a;}
    public static void main(String[] args) throws IOException
    {
        Reader r = new Reader();

        int i, j;

        long N = r.nextLong();
        int M = r.nextInt();

        if (N < M)
        {
            System.out.println(1);
            System.exit(0);
        }

        long[][] A = new long[M][M];
        long[][] P = new long[M][M];
        long[][] store = new long[M][M];

        Arrays.fill(A[0], 1);
        A[0][M - 1] = 2;
        for (i = 1; i < M; i++) P[i][i - 1] = 1;
        P[0][M - 1] = P[M - 1][M - 1] = 1;

        pow(P, M, N - M);
        multiply(A, P, store, M);

        System.out.println(A[0][M - 1]);
    }
    static class Reader
    {
        final private int BUFFER_SIZE = 1 << 16;private DataInputStream din;private byte[] buffer;private int bufferPointer, bytesRead;
        public Reader(){din=new DataInputStream(System.in);buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public Reader(String file_name) throws IOException{din=new DataInputStream(new FileInputStream(file_name));buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public String readLine() throws IOException{byte[] buf=new byte[64];int cnt=0,c;while((c=read())!=-1){if(c=='\n')break;buf[cnt++]=(byte)c;}return new String(buf,0,cnt);
        }public int nextInt() throws IOException{int ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
        }public long nextLong() throws IOException{long ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
        }public double nextDouble() throws IOException{double ret=0,div=1;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c = read();do {ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(c=='.')while((c=read())>='0'&&c<='9')ret+=(c-'0')/(div*=10);if(neg)return -ret;return ret;
        }private void fillBuffer() throws IOException{bytesRead=din.read(buffer,bufferPointer=0,BUFFER_SIZE);if(bytesRead==-1)buffer[0]=-1;
        }private byte read() throws IOException{if(bufferPointer==bytesRead)fillBuffer();return buffer[bufferPointer++];
        }public void close() throws IOException{if(din==null) return;din.close();}
    }
}

//created by Whiplash99
import java.io.*;
import java.util.*;
public class D
{
    private static final long MOD=(long)(1e9+7);
    static class Matrix
    {
        long[][] M; int N;
        Matrix(int N){this.N=N; M=new long[N][N];}
        void makeIdentity(){for(int i=0;i<N;i++) M[i][i]=1;}
        void copy(Matrix source)
        {
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    M[i][j]=source.M[i][j];
        }
        void multiply(Matrix B, Matrix C)
        {
            for(int i=0;i<N;i++) Arrays.fill(C.M[i],0);
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    for(int k=0;k<N;k++)
                        C.M[i][j]=add(C.M[i][j],prod(M[i][k],B.M[k][j]));
            copy(C);
        }
        void pow(long b)
        {
            Matrix res=new Matrix(N), store=new Matrix(N);
            res.makeIdentity();
            while (b>0)
            {
                if((b&1)==1) res.multiply(this,store);
                this.multiply(this,store);
                b>>=1;
            }
            copy(res);
        }
    }
    private static long add(long a, long b){a+=b; return (a>=MOD)?a-MOD:a;}
    private static long prod(long a, long b){a*=b; return (a>=MOD)?a%MOD:a;}
    public static void main(String[] args) throws IOException
    {
        Reader r=new Reader();

        int i,j;

        long N=r.nextLong();
        int M=r.nextInt();

        if(N<M){ System.out.println(1); System.exit(0);}

        Matrix A=new Matrix(M);
        Matrix P=new Matrix(M);
        Matrix store=new Matrix(M);

        Arrays.fill(A.M[0],1); A.M[0][M-1]=2;
        for(i=1;i<M;i++) P.M[i][i-1]=1; P.M[0][M-1]=P.M[M-1][M-1]=1;

        P.pow(N-M);
        A.multiply(P,store);

        System.out.println(A.M[0][M-1]);
    }
    static class Reader
    {
        final private int BUFFER_SIZE = 1 << 16;private DataInputStream din;private byte[] buffer;private int bufferPointer, bytesRead;
        public Reader(){din=new DataInputStream(System.in);buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public Reader(String file_name) throws IOException{din=new DataInputStream(new FileInputStream(file_name));buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
    }public String readLine() throws IOException{byte[] buf=new byte[64];int cnt=0,c;while((c=read())!=-1){if(c=='\n')break;buf[cnt++]=(byte)c;}return new String(buf,0,cnt);
    }public int nextInt() throws IOException{int ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
    }public long nextLong() throws IOException{long ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
    }public double nextDouble() throws IOException{double ret=0,div=1;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c = read();do {ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(c=='.')while((c=read())>='0'&&c<='9')ret+=(c-'0')/(div*=10);if(neg)return -ret;return ret;
    }private void fillBuffer() throws IOException{bytesRead=din.read(buffer,bufferPointer=0,BUFFER_SIZE);if(bytesRead==-1)buffer[0]=-1;
    }private byte read() throws IOException{if(bufferPointer==bytesRead)fillBuffer();return buffer[bufferPointer++];
    }public void close() throws IOException{if(din==null) return;din.close();}
    }
}

import java.util.*;

import java.io.*;

   public class codeforces {
    public static long[][] matmult(long[][]a,long[][]b){
    	int n=a.length;
    	int m=b.length;
    	int l=b[0].length;
    	long[][] c=new long[n][l];
    	for(int i=0;i<n;i++) {
    		for(int j=0;j<l;j++) {
    			long ans=0;
    			for(int k=0;k<m;k++) {
    				ans=(ans+a[i][k]*1l*b[k][j])%mod;

    			}
    			c[i][j]= (ans);
    		}
    	}
    	return c;
    }
    public static long[][] matexo(long[][]a,long n){
    		long[][]ret=new long[a.length][a.length];
    		for(int i=0;i<a.length;i++) {
    			ret[i][i]=1;
    		}

    		while(n>0) {
    			if(n%2==1) {
    				ret=matmult(a, ret);
    			}
    			a=matmult(a, a);
    			n=n/2;
    		}
    		return ret;
   }

    public static void main(String[] args) throws Exception {
        long n=sc.nextLong();
       int m=sc.nextInt();
       long[][]a=new long[m][m];
       for(int i=0;i<m-1;i++) {
    	   a[i][i+1]=1;
       }
       a[m-1][0]=1;
       a[m-1][m-1]=1;
       long[][]c=new long[m][1];
       for(int i=0;i<m;i++) {
    	   c[i][0]=1;
       }
       long[][]b=matmult(matexo(a, n), c);
       pw.println(b[0][0]);
       pw.close();
    }

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s) {
			br = new BufferedReader(new InputStreamReader(s));
		}

		public Scanner(FileReader r) {
			br = new BufferedReader(r);
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		public long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public String nextLine() throws IOException {
			return br.readLine();
		}

		public double nextDouble() throws IOException {
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if (x.charAt(0) == '-') {
				neg = true;
				start++;
			}
			for (int i = start; i < x.length(); i++)
				if (x.charAt(i) == '.') {
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				} else {
					sb.append(x.charAt(i));
					if (dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg ? -1 : 1);
		}
		public long[] nextlongArray(int n) throws IOException {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
                a[i] = nextLong();
            return a;
        }
		public Long[] nextLongArray(int n) throws IOException {
            Long[] a = new Long[n];
            for (int i = 0; i < n; i++)
                a[i] = nextLong();
            return a;
        }
		public int[] nextIntArray(int n) throws IOException {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }
		public Integer[] nextIntegerArray(int n) throws IOException {
            Integer[] a = new Integer[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }
		public boolean ready() throws IOException {
			return br.ready();
		}

	}

	static class pair implements Comparable<pair> {
		long x;
		long y;

		public pair(long x, long y) {
			this.x = x;
			this.y = y;
		}

		public String toString() {
			return x + " " + y;
		}
		public boolean equals(Object o) {
            if (o instanceof pair) {
                pair p = (pair)o;
                return p.x == x && p.y == y;
            }
            return false;
        }
        public int hashCode() {
            return new Double(x).hashCode() * 31 + new Double(y).hashCode();
        }
        public int compareTo(pair other) {
        	if(this.x==other.x) {
        		return Long.compare(this.y, other.y);
        	}
			return Long.compare(this.x, other.x);
		}
	}

	static class tuble implements Comparable<tuble> {
		int x;
		int y;
		int z;

		public tuble(int x, int y, int z) {
			this.x = x;
			this.y = y;
			this.z = z;
		}

		public String toString() {
			return x + " " + y + " " + z;
		}

		public int compareTo(tuble other) {
			if (this.x == other.x) {
				if(this.y==other.y) {
					return this.z - other.z;
				}
				return this.y - other.y;
			} else {
				return this.x - other.x;
			}
		}
	}

	public static long GCD(long a, long b) {
		if (b == 0)
			return a;
		if (a == 0)
			return b;
		return (a > b) ? GCD(a % b, b) : GCD(a, b % a);
	}

	public static long LCM(long a, long b) {
		return a * b / GCD(a, b);
	}

	static long Pow(long a, long e, long mod) // O(log e)
	{
		a %= mod;
		long res = 1l;
		while (e > 0) {
			if ((e & 1) == 1)
				res = (res * a) % mod;
			a = (a * a) % mod;
			e >>= 1l;
		}
		return res;
	}
   public static long modinverse(long a,long mod) {
	   return Pow(a, mod-2, mod);
   }
	static long nc(int n, int r) {
		if (n < r)
			return 0;
		long v = fac[n];
		v *= Pow(fac[r], mod - 2, mod);
		v %= mod;
		v *= Pow(fac[n - r], mod - 2, mod);
		v %= mod;
		return v;
	}

	public static boolean isprime(long a) {
		if (a == 0 || a == 1) {
			return false;
		}
		if (a == 2) {
			return true;
		}
		for (int i = 2; i < Math.sqrt(a) + 1; i++) {
			if (a % i == 0) {
				return false;
			}
		}
		return true;
	}

	public static boolean isPal(String s) {
		boolean t = true;
		for (int i = 0; i < s.length(); i++) {
			if (s.charAt(i) != s.charAt(s.length() - 1 - i)) {
				t = false;
				break;
			}
		}
		return t;
	}

	public static long RandomPick(long[] a) {
		int n = a.length;
		int r = rn.nextInt(n);
		return a[r];
	}

	public static int RandomPick(int[] a) {
		int n = a.length;
		int r = rn.nextInt(n);
		return a[r];
	}
 static class hash {
	 int[]HashsArray;
	 boolean reverse;
	 int prelen;
	public  hash(String s, boolean r) {
		prelen = s.length();
		reverse=r;
		HashsArray = new int[prelen + 1];
		if (HashsArrayInd == 0) {
			int[] mods = { 1173017693, 1173038827, 1173069731, 1173086977, 1173089783, 1173092147, 1173107093,
					1173114391, 1173132347, 1173144367, 1173150103, 1173152611, 1173163993, 1173174127, 1173204679,
					1173237343, 1173252107, 1173253331, 1173255653, 1173260183, 1173262943, 1173265439, 1173279091,
					1173285331, 1173286771, 1173288593, 1173298123, 1173302129, 1173308827, 1173310451, 1173312383,
					1173313571, 1173324371, 1173361529, 1173385729, 1173387217, 1173387361, 1173420799, 1173421499,
					1173423077, 1173428083, 1173442159, 1173445549, 1173451681, 1173453299, 1173454729, 1173458401,
					1173459491, 1173464177, 1173468943, 1173470041, 1173477947, 1173500677, 1173507869, 1173522919,
					1173537359, 1173605003, 1173610253, 1173632671, 1173653623, 1173665447, 1173675577, 1173675787,
					1173684683, 1173691109, 1173696907, 1173705257, 1173705523, 1173725389, 1173727601, 1173741953,
					1173747577, 1173751499, 1173759449, 1173760943, 1173761429, 1173762509, 1173769939, 1173771233,
					1173778937, 1173784637, 1173793289, 1173799607, 1173802823, 1173808003, 1173810919, 1173818311,
					1173819293, 1173828167, 1173846677, 1173848941, 1173853249, 1173858341, 1173891613, 1173894053,
					1173908039, 1173909203, 1173961541, 1173968989, 1173999193};
			mod = RandomPick(mods);
			int[] primes = { 59, 61, 67, 71, 73, 79, 83, 89, 97, 101 };
			prime = RandomPick(primes);
			prepow = new int[1000010];
			prepow[0] = 1;
			for (int i = 1; i < 1000010; i++) {
				prepow[i] = (int) ((1l * prepow[i - 1] * prime) % mod);

			}
		}
		if (!reverse) {

			for (int i = 0; i < prelen; i++) {
				if (s.charAt(i) >= 'a' && s.charAt(i) <= 'z')
					HashsArray[i + 1] = (int) ((1l * HashsArray[i]
							+ ((1l * s.charAt(i) - 'a' + 1) *prepow[i]) % mod) % mod);
				else
					HashsArray[i + 1] = (int) ((1l * HashsArray[i]
							+ ((1l * s.charAt(i) - 'A' + 27) * prepow[i]) % mod) % mod);
			}

		} else {

			for (int i = 0; i < prelen; i++) {
				if (s.charAt(i) >= 'a' && s.charAt(i) <= 'z')
					HashsArray[i + 1] = (int) ((1l * HashsArray[i]
							+ ((1l * s.charAt(i) - 'a' + 1) * prepow[1000010 - 1 - i]) % mod) % mod);
				else
					HashsArray[i + 1] = (int) ((1l * HashsArray[i]
							+ ((1l * s.charAt(i) - 'A' + 27) * prepow[1000010 - 1 - i]) % mod) % mod);
			}

		}

		HashsArrayInd++;

	}

	public int PHV(int l, int r) {
		if (l > r) {
			return 0;
		}
		int val = (int) ((1l * HashsArray[r] + mod - HashsArray[l - 1]) % mod);
		if (!reverse) {

//			val = (int) ((1l * val *  modinverse(prepow[l-1], mod)) % mod);
			val = (int) ((1l * val * prepow[1000010 - l]) % mod);
		} else {
//			val = (int) ((1l * val * modinverse(prepow[prelen-r], mod)) % mod);

			val = (int) ((1l * val * prepow[r - 1]) % mod);
		}
		return val;
	}
 }
    public static void genprime(int n) {
    	 boolean prime[] = new boolean[n+1];
         for(int i=0;i<n;i++)
             prime[i] = true;

         for(int p = 2; p*p <=n; p++)
         {
             if(prime[p] == true)
             {
                 for(int i = p*p; i <= n; i += p)
                     prime[i] = false;
             }
         }
         for(int i = 2; i <= n; i++)
         {
             if(prime[i] == true) {
                primes.put(i,primes.size());
                primes2.put(primes2.size(),i);
             }

         }
    }

    public static long LSB(long x) {
		return x&-x;
	}
	static class fenwick {
		long[] arr;
		public fenwick(PriorityQueue<Integer> a) {
			PriorityQueue<Integer>q=new PriorityQueue<Integer>(a);
			arr=new long[a.size()+1];
			int i=1;
			while(!q.isEmpty()) {
				int z=q.poll();
				arr[i]+=z;
				if(i+LSB(i)<=a.size()) {
					arr[(int) (i+LSB(i))]+=arr[i];
				}
				i++;
			}
		}
		public fenwick(TreeSet<Integer> a) {
			arr=new long[a.size()+1];
			int i=1;
			for(int h:a) {
				arr[i]+=h;
				if(i+LSB(i)<=a.size()) {
					arr[(int) (i+LSB(i))]+=arr[i];
				}
				i++;
			}
		}
		public fenwick(Integer[] a) {
			arr=new long[a.length+1];
			for(int i=1;i<=a.length;i++) {
				arr[i]+=a[i-1];
				if(i+LSB(i)<=a.length) {
					arr[(int) (i+LSB(i))]+=arr[i];
				}
			}
		}
		public fenwick(int[] a) {
			arr=new long[a.length+1];
			for(int i=1;i<=a.length;i++) {
				arr[i]+=a[i-1];
				if(i+LSB(i)<=a.length) {
					arr[(int) (i+LSB(i))]+=arr[i];
				}
			}
		}public fenwick(long[] a) {
			arr=new long[a.length+1];
			for(int i=1;i<=a.length;i++) {
				arr[i]+=a[i];
				if(i+LSB(i)<=a.length) {
					arr[(int) (i+LSB(i))]+=arr[i];
				}
			}
		}
		public void update(int ind,long x) {
			int i=ind;
			while(i<arr.length) {
				arr[i]+=x;
				i+=LSB(i);
			}
		}
		public long PrefixSum(int ind) {
			long sum=0;
			int i=ind;
			while(i>0) {
				sum+=arr[i];
				i=(int) (i-LSB(i));
			}
			return sum;
		}
		public long RangeQuerey(int l,int r) {
			return  this.PrefixSum(r+1)-this.PrefixSum(l);
		}
		public long maxConsecutiveValue(int k) {
			long max=Long.MIN_VALUE;
			for(int i=k-1;i<arr.length-1;i++) {

				max= Math.max(max,  this.RangeQuerey(i-k+1, i));

			}
			return max;
		}
		public long minConsecutiveValue(int k) {
			long min=Long.MAX_VALUE;

			for(int i=k-1;i<arr.length-1;i++) {

				min= Math.min(min,  this.RangeQuerey(i-k+1, i));

			}
			return min;
		}
		public long value(int ind) {
			return arr[ind];
		}
	}
	static void sieveLinear(int N)
	{
		ArrayList<Integer> primes = new ArrayList<Integer>();
		lp = new int[N + 1];								//lp[i] = least prime divisor of i
		for(int i = 2; i <= N; ++i)
		{
			if(lp[i] == 0)
			{
				primes.add(i);
				lp[i] = i;
			}
			int curLP = lp[i];
			for(int p: primes)//all primes smaller than or equal my lowest prime divisor
				if(p > curLP || p * 1l * i > N)
					break;
				else
					lp[p * i] = p;
		}
	}
	public static void primefactorization(int n) {
		int x=n;
	while(x>1) {
		int lowestDivisor=lp[x];
		while(x%lowestDivisor==0) {
			primefactors.add(lowestDivisor);
			x/=lowestDivisor;
		}
	}
	}
	public static class SuffixArray {

		int[] SA;
		int[] AS;
		String SS;
		public SuffixArray(String S)					//has a terminating character (e.g. '$')
		{
			SS=S;
			char[] s=new char[S.length()+1];
			for(int i=0;i<S.length();i++) {
				s[i]=S.charAt(i);
			}
			s[S.length()]='$';
			int n = s.length, RA[] = new int[n];
			SA = new int[n];

			for(int i = 0; i < n; ++i) { RA[i] = s[i]; SA[i] = i; }

			for(int k = 1; k < n; k <<= 1)
			{
				sort(SA, RA, n, k);
				sort(SA, RA, n, 0);
				int[] tmp = new int[n];

				for(int i = 1, r = 0, s1 = SA[0], s2; i < n; ++i)
				{
					s2 = SA[i];
					tmp[s2] = RA[s1] == RA[s2] && RA[s1 + k] == RA[s2 + k] ? r : ++r;
					s1 = s2;
				}
				for(int i = 0; i < n; ++i)
					RA[i] = tmp[i];

				if(RA[SA[n-1]] == n - 1)
					break;
			}
			AS=new int[SA.length];
			for(int i=0;i<SA.length;i++) {
				AS[SA[i]]=i;
			}
		}
		public String toString() {

			return Arrays.toString(SA);
		}
		public int get(int n) {
			return SA[n];
		}
		public int Substring(String s) {  // log(n)*|s|
			int low=0;
			int high=SA.length;
			int mid=(low+high)/2;
			int ind=-1;

			while(low<high-1) {

				if(SS.length()-SA[mid]<s.length()) {

					boolean less=false;
					for(int i=SA[mid];i<SS.length();i++) {
						if(SS.charAt(i)>s.charAt(i-SA[mid])) {
							less=true;
							break;
						}
						if(SS.charAt(i)<s.charAt(i-SA[mid])) {
							less=false;
							break;
						}
					}
					if(!less) {
						low=mid;
					}else {
						high=mid;
					}
				}else {
					boolean less=true;
					boolean equal=true;
					for(int i=SA[mid];i<SA[mid]+s.length();i++) {
						if(SS.charAt(i)<s.charAt(i-SA[mid])&&equal) {
							less=false;
							equal=false;
							break;
						}
						if(SS.charAt(i)!=s.charAt(i-SA[mid])){
							equal=false;
						}
					}
					if(equal) {
						ind=SA[mid];
					}
					if(!less) {
						low=mid;
					}else {
						high=mid;
					}
				}

				mid=(low+high)/2;
			}
			return ind;
		}
		public int LastSubstring(String s) {  // log(n)*|s|
			int low=0;
			int high=SA.length;
			int mid=(low+high)/2;
			int ind=-1;

			while(low<high-1) {

				if(SS.length()-SA[mid]<s.length()) {

					boolean less=true;
					for(int i=SA[mid];i<SS.length();i++) {
						if(SS.charAt(i)<s.charAt(i-SA[mid])) {
							break;
						}
						if(SS.charAt(i)>s.charAt(i-SA[mid])) {
							less=false;
							break;
						}
					}
					if(less) {
						low=mid;
					}else {
						high=mid;
					}
				}else {
					boolean less=true;
					boolean equal=true;
					for(int i=SA[mid];i<SA[mid]+s.length();i++) {
						if(SS.charAt(i)>s.charAt(i-SA[mid])&&equal) {
							less=false;
							equal=false;
							break;
						}
						if(SS.charAt(i)!=s.charAt(i-SA[mid])){
							equal=false;
						}
					}
					if(equal) {
						ind=SA[mid];
					}
					if(less) {
						low=mid;
					}else {
						high=mid;
					}
				}

				mid=(low+high)/2;
			}
			return ind;
		}
		public int CountSubstring(String s) {
			int z=LastSubstring(s);
			if(z==-1)
				return 0;
			return AS[z]-AS[Substring(s)]+1;
		}
		public void sort(int[] SA, int[] RA, int n, int k)
		{
			int maxi = Math.max(256, n), c[] = new int[maxi];
			for(int i = 0; i < n; ++i)
				c[i + k < n ? RA[i + k] : 0]++;
			for(int i = 0, sum = 0; i < maxi; ++i)
			{
				int t = c[i];
				c[i] = sum;
				sum += t;
			}
			int[] tmp = new int[n];
			for(int i = 0; i < n; ++i)
			{
				int j = SA[i] + k;
				tmp[c[j < n ? RA[j] : 0]++] = SA[i];
			}

			for(int i = 0; i < n; ++i)
				SA[i] = tmp[i];
		}
	}
	static LinkedList<Integer>primefactors=new LinkedList<>();
	static TreeMap<Integer,Integer>primes=new TreeMap<Integer, Integer>();
	static TreeMap<Integer,Integer>primes2=new TreeMap<Integer, Integer>();
	static int[]lp;

	static int HashsArrayInd = 0;
	static int[] prepow;
	static int prime = 61;
	static long fac[];
	static long mod = 1000000007;
	static Random rn = new Random();
	static Scanner sc = new Scanner(System.in);
	static PrintWriter pw = new PrintWriter(System.out);
}

//created by Whiplash99
import java.io.*;
import java.util.*;
public class F
{
    private static final long MOD=(long)(1e9+7);
    static class Matrix
    {
        long[][] M; int N;
        Matrix(int N){this.N=N; M=new long[N][N];}
        void makeIdentity(){for(int i=0;i<N;i++) M[i][i]=1;}
        void copy(Matrix source)
        {
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    M[i][j]=source.M[i][j];
        }
        void multiply(Matrix B, Matrix C)
        {
            for(int i=0;i<N;i++) Arrays.fill(C.M[i],0);
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    for(int k=0;k<N;k++)
                        C.M[i][j]=(C.M[i][j]+M[i][k]*B.M[k][j]%MOD)%MOD;
            copy(C);
        }
        void pow(long b)
        {
            Matrix res=new Matrix(N), store=new Matrix(N);
            res.makeIdentity();
            while (b>0)
            {
                if((b&1)==1) res.multiply(this,store);
                this.multiply(this,store);
                b>>=1;
            }
            copy(res);
        }
    }
    public static void main(String[] args) throws IOException
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

        int i,j;

        String s[]=br.readLine().trim().split(" ");
        long N=Long.parseLong(s[0]);
        int M=Integer.parseInt(s[1]);

        if(N<M){ System.out.println(1); System.exit(0);}

        Matrix A=new Matrix(M);
        Matrix P=new Matrix(M);
        Matrix store=new Matrix(M);

        Arrays.fill(A.M[0],1); A.M[0][M-1]=2;
        for(i=1;i<M;i++) P.M[i][i-1]=1; P.M[0][M-1]=P.M[M-1][M-1]=1;

        P.pow(N-M);
        A.multiply(P,store);

        System.out.println(A.M[0][M-1]);
    }
}

//package educational.round60;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class D {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		long n = nl();
		int m = ni();
		int[][] M = new int[m][m];
		for(int i = 0;i < m-1;i++){
			M[i+1][i] = 1;
		}
		M[0][0] = 1;
		M[0][m-1] = 1;

		int[] v = new int[m];
		v[0] = 1;
		out.println(pow(M, v, n)[0]);
	}

	public static final int mod = 1000000007;
	public static final long m2 = (long)mod*mod;
	public static final long BIG = 8L*m2;

	// A^e*v
	public static int[] pow(int[][] A, int[] v, long e)
	{
		for(int i = 0;i < v.length;i++){
			if(v[i] >= mod)v[i] %= mod;
		}
		int[][] MUL = A;
		for(;e > 0;e>>>=1) {
			if((e&1)==1)v = mul(MUL, v);
			MUL = p2(MUL);
		}
		return v;
	}

	// int matrix*int vector
	public static int[] mul(int[][] A, int[] v)
	{
		int m = A.length;
		int n = v.length;
		int[] w = new int[m];
		for(int i = 0;i < m;i++){
			long sum = 0;
			for(int k = 0;k < n;k++){
				sum += (long)A[i][k] * v[k];
				if(sum >= BIG)sum -= BIG;
			}
			w[i] = (int)(sum % mod);
		}
		return w;
	}

	// int matrix^2 (be careful about negative value)
	public static int[][] p2(int[][] A)
	{
		int n = A.length;
		int[][] C = new int[n][n];
		for(int i = 0;i < n;i++){
			long[] sum = new long[n];
			for(int k = 0;k < n;k++){
				for(int j = 0;j < n;j++){
					sum[j] += (long)A[i][k] * A[k][j];
					if(sum[j] >= BIG)sum[j] -= BIG;
				}
			}
			for(int j = 0;j < n;j++){
				C[i][j] = (int)(sum[j] % mod);
			}
		}
		return C;
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new D().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}

import java.io.*;
import java.util.*;

public class D implements Runnable {
	FastReader scn;
	PrintWriter out;
	String INPUT = "1 2";

	long mod = 1000_000_000 + 7;

	void solve() {
		long n = scn.nextLong();
		int m = scn.nextInt();
		if (n < m) {
			out.println(1);
			return;
		}

		long[][] gen = new long[m][m];
		gen[0][0] = gen[0][m - 1] = 1;
		for(int i = 1; i < m; i++) {
			gen[i][i - 1] = 1;
		}

		long rv = f(n, gen);
		out.println(rv);
	}

	long f(long n, long[][] gen) {
		long[][] rv = f(gen, gen, n);
		return rv[0][0];
	}

	long[][] f(long[][] mat, long[][] gen, long n){
		if(n == 1) {
			return gen;
		}

		long[][] rv = f(mat, gen, n / 2);
		rv = multiply(rv, rv, mod);
		if(n % 2 == 1) {
			rv = multiply(rv, gen, mod);
		}
		return rv;
	}

	long[][] multiply(long[][] a, long[][] b, long mod) {
		if (a[0].length != b.length) {
			return null;
		}

		long[][] rv = new long[a.length][b[0].length];
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < b[0].length; j++) {
				for (int k = 0; k < b.length; k++) {
					rv[i][j] += (a[i][k] * b[k][j]) % mod;
					rv[i][j] %= mod;
				}
			}
		}

		return rv;
	}

	public void run() {
		long time = System.currentTimeMillis();
		boolean oj = System.getProperty("ONLINE_JUDGE") != null;
		out = new PrintWriter(System.out);
		scn = new FastReader(oj);
		solve();
		out.flush();
		if (!oj) {
			System.out.println(Arrays.deepToString(new Object[] { System.currentTimeMillis() - time + " ms" }));
		}
	}

	public static void main(String[] args) {
		new Thread(null, new D(), "1", 1 << 26).start();
	}

	class FastReader {
		InputStream is;

		public FastReader(boolean onlineJudge) {
			is = onlineJudge ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		}

		byte[] inbuf = new byte[1024];
		public int lenbuf = 0, ptrbuf = 0;

		int readByte() {
			if (lenbuf == -1)
				throw new InputMismatchException();
			if (ptrbuf >= lenbuf) {
				ptrbuf = 0;
				try {
					lenbuf = is.read(inbuf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (lenbuf <= 0)
					return -1;
			}
			return inbuf[ptrbuf++];
		}

		boolean isSpaceChar(int c) {
			return !(c >= 33 && c <= 126);
		}

		int skip() {
			int b;
			while ((b = readByte()) != -1 && isSpaceChar(b))
				;
			return b;
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}

		char nextChar() {
			return (char) skip();
		}

		String next() {
			int b = skip();
			StringBuilder sb = new StringBuilder();
			while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
				sb.appendCodePoint(b);
				b = readByte();
			}
			return sb.toString();
		}

		String nextLine() {
			int b = skip();
			StringBuilder sb = new StringBuilder();
			while ((!isSpaceChar(b) || b == ' ')) { // when nextLine, (isSpaceChar(b) && b != ' ')
				sb.appendCodePoint(b);
				b = readByte();
			}
			return sb.toString();
		}

		char[] next(int n) {
			char[] buf = new char[n];
			int b = skip(), p = 0;
			while (p < n && !(isSpaceChar(b))) {
				buf[p++] = (char) b;
				b = readByte();
			}
			return n == p ? buf : Arrays.copyOf(buf, p);
		}

		int nextInt() {
			int num = 0, b;
			boolean minus = false;
			while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
				;
			if (b == '-') {
				minus = true;
				b = readByte();
			}

			while (true) {
				if (b >= '0' && b <= '9') {
					num = num * 10 + (b - '0');
				} else {
					return minus ? -num : num;
				}
				b = readByte();
			}
		}

		long nextLong() {
			long num = 0;
			int b;
			boolean minus = false;
			while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
				;
			if (b == '-') {
				minus = true;
				b = readByte();
			}

			while (true) {
				if (b >= '0' && b <= '9') {
					num = num * 10 + (b - '0');
				} else {
					return minus ? -num : num;
				}
				b = readByte();
			}
		}

		char[][] nextMatrix(int n, int m) {
			char[][] map = new char[n][];
			for (int i = 0; i < n; i++)
				map[i] = next(m);
			return map;
		}

		int[] nextIntArray(int n) {
			int[] a = new int[n];
			for (int i = 0; i < n; i++)
				a[i] = nextInt();
			return a;
		}

		long[] nextLongArray(int n) {
			long[] a = new long[n];
			for (int i = 0; i < n; i++)
				a[i] = nextLong();
			return a;
		}

		int[][] next2DInt(int n, int m) {
			int[][] arr = new int[n][];
			for (int i = 0; i < n; i++) {
				arr[i] = nextIntArray(m);
			}
			return arr;
		}

		long[][] next2DLong(int n, int m) {
			long[][] arr = new long[n][];
			for (int i = 0; i < n; i++) {
				arr[i] = nextLongArray(m);
			}
			return arr;
		}

		int[] shuffle(int[] arr) {
			Random r = new Random();
			for (int i = 1, j; i < arr.length; i++) {
				j = r.nextInt(i);
				arr[i] = arr[i] ^ arr[j];
				arr[j] = arr[i] ^ arr[j];
				arr[i] = arr[i] ^ arr[j];
			}
			return arr;
		}

		int[] uniq(int[] arr) {
			Arrays.sort(arr);
			int[] rv = new int[arr.length];
			int pos = 0;
			rv[pos++] = arr[0];
			for (int i = 1; i < arr.length; i++) {
				if (arr[i] != arr[i - 1]) {
					rv[pos++] = arr[i];
				}
			}
			return Arrays.copyOf(rv, pos);
		}

		int[] reverse(int[] arr) {
			int l = 0, r = arr.length - 1;
			while (l < r) {
				arr[l] = arr[l] ^ arr[r];
				arr[r] = arr[l] ^ arr[r];
				arr[l] = arr[l] ^ arr[r];
				l++;
				r--;
			}
			return arr;
		}

	}
}

import java.util.*;
import java.io.*;
import static java.lang.Math.*;

/* spar5h */

public class cf4 implements Runnable {

	final static long mod = (long)1e9 + 7;

	static long[][] mat;

	static void init(int m) {

		mat = new long[m][m];

		mat[0][0] = 1;
		mat[0][m - 1] = 1;

		for(int i = 1; i < m; i++)
			mat[i][i - 1] = 1;
	}

	static long[][] multiply(long[][] a, long[][] b) {

		int m = a.length;

		long[][] c = new long[m][m];

		for(int i = 0; i < m; i++)
			for(int j = 0; j < m; j++)
				for(int k = 0; k < m; k++)
					c[i][j] = (c[i][j] + a[i][k] * b[k][j] % mod) % mod;

		return c;
	}

	static long[][] modExp(long[][] a, long y) {

		if(y == 1)
			return a;

		long[][] ret = modExp(a, y / 2);
		ret = multiply(ret, ret);

		if(y % 2 == 1)
			ret = multiply(ret, mat);

		return ret;
	}

	static long f(long n, int m) {

		if(n < m)
			return 1L;

		long[][] a = modExp(mat, n - m + 1);

		long ret = 0;

		for(int i = 0; i < m; i++)
			ret = (ret + a[0][i]) % mod;

		return ret;
	}

	public void run() {

		InputReader s = new InputReader(System.in);
		PrintWriter w = new PrintWriter(System.out);

		long n = s.nextLong();
		int m = s.nextInt();

		init(m);

		w.println(f(n, m));

		w.close();
	}

	static class InputReader {

		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;
		private SpaceCharFilter filter;

		public InputReader(InputStream stream) {
			this.stream = stream;
		}

		public int read() {

			if (numChars==-1)
				throw new InputMismatchException();

			if (curChar >= numChars) {

				curChar = 0;

				try {
					numChars = stream.read(buf);
				}
				catch (IOException e) {
					throw new InputMismatchException();
				}

				if(numChars <= 0)
					return -1;
			}

			return buf[curChar++];
		}

		public String nextLine() {

			BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
			String str = "";

			try {
	            str = br.readLine();
	        }
	        catch (IOException e) {
	            e.printStackTrace();
	        }

	        return str;
		}

		public int nextInt() {

			int c = read();

			while(isSpaceChar(c))
				c = read();

			int sgn = 1;

			if (c == '-') {
				sgn = -1;
				c = read();
			}

			int res = 0;

			do {
				if(c<'0'||c>'9')
					throw new InputMismatchException();

				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));

			return res * sgn;
		}

		public long nextLong() {

			int c = read();

			while (isSpaceChar(c))
				c = read();

			int sgn = 1;

			if (c == '-') {
				sgn = -1;
				c = read();
			}

			long res = 0;

			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();

				res *= 10;
				res += c - '0';
				c = read();
			}

			while (!isSpaceChar(c));
				return res * sgn;
		}

		public double nextDouble() {

			int c = read();

			while (isSpaceChar(c))
				c = read();

			int sgn = 1;

			if (c == '-') {
				sgn = -1;
				c = read();
			}

			double res = 0;

			while (!isSpaceChar(c) && c != '.') {

				if (c == 'e' || c == 'E')
					return res * Math.pow(10, nextInt());

				if (c < '0' || c > '9')
					throw new InputMismatchException();

				res *= 10;
				res += c - '0';
				c = read();
			}

			if (c == '.') {

				c = read();
				double m = 1;
				while (!isSpaceChar(c))
				{
					if (c == 'e' || c == 'E')
						return res * Math.pow(10, nextInt());
					if (c < '0' || c > '9')
						throw new InputMismatchException();
					m /= 10;
					res += (c - '0') * m;
					c = read();
				}
			}

			return res * sgn;
		}

		public String readString() {

			int c = read();

			while (isSpaceChar(c))
				c = read();

			StringBuilder res = new StringBuilder();

			do {
				res.appendCodePoint(c);
				c = read();
			}
			while (!isSpaceChar(c));

			return res.toString();
		}

		public boolean isSpaceChar(int c) {

			if (filter != null)
				return filter.isSpaceChar(c);

			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public String next() {
			return readString();
		}

		public interface SpaceCharFilter {
			public boolean isSpaceChar(int ch);
		}

	}

	public static void main(String args[]) throws Exception {
		new Thread(null, new cf4(),"cf4",1<<26).start();
	}
}

import java.io.*;
import java.util.InputMismatchException;

public class MagicGems {

    private static boolean LOCAL;
    static {
        try { LOCAL = "aurel".equalsIgnoreCase(System.getenv().get("USER")); } catch (Exception e){}
    }

    private static final String TEST =
        "3 2";

    void solve(InputReader in, PrintWriter out) {
        long n = in.nextLong();
        int m = in.nextInt();
        if (n < m) {
            out.println(1);
            return;
        }

        long mod = 1_000_000_007;
        long[][] a = new long[m][m];
        a[0][0] = a[0][m - 1] = 1;
        for (int i = 1; i < m; i++) {
            a[i][i - 1] = 1;
        }

        a = powMod(a, n - m + 1, mod);
        long ans = 0;
        for (int i = 0; i < m; i++) {
            ans = (ans + a[0][i]) % mod;
        }
        System.out.println(ans);
    }

    private static long[][] powMod(long[][] a, long b, long mod) {
        int n = a.length;
        long[][] p = eye(n);
        while (b > 0) {
            if (b % 2 == 1) {
                p = mul(p, a, mod);
            }
            a = mul(a, a, mod);
            b /= 2;
        }
        return p;
    }

    private static long[][] mul(long[][] a, long[][] b, long mod) {
        int n = a.length;
        long[][] c = new long[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < n; k++) {
                    c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % mod;
                }
            }
        }
        return c;
    }

    private static long[][] eye(int n) {
        long[][] a = new long[n][n];
        for (int i = 0; i < n; i++) {
            a[i][i] = 1;
        }
        return a;
    }

    //region main
    public static void main(String[] args) throws Exception {
        long t = System.currentTimeMillis();

        try (
            InputReader in = new StreamInputReader(!LOCAL ? System.in : new ByteArrayInputStream(TEST.getBytes()));
            PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out, 2048), false)
        ) {
            new MagicGems().solve(in, out);
        }

        System.err.println("time: " + (System.currentTimeMillis() - t) + "ms");
    }
    //endregion

    //region fast io
    abstract static class InputReader implements AutoCloseable {

        public abstract int read();

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public String next() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isSpaceChar(c));
            return res.toString();
        }

        public boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }
    }

    static class StreamInputReader extends InputReader {

        private InputStream stream;
        private byte[] buf;
        private int curChar, numChars;

        public StreamInputReader(InputStream stream) {
            this(stream, 2048);
        }

        public StreamInputReader(InputStream stream, int bufSize) {
            this.stream = stream;
            this.buf = new byte[bufSize];
        }

        @Override
        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        @Override
        public void close() throws Exception {
            stream.close();
        }

    }
    //endregion

    //region imports
    //endregion

}

import java.util.*;

public class MagicGems
{

	public static void main(String[] args)
	{
		Scanner scan = new Scanner(System.in);
		long n = scan.nextLong();
		int m = scan.nextInt();
		if(n < m) {
			System.out.println(1);
			return;
		}
		long[][] mat = new long[m][m];
		mat[0][0] = 1;
		mat[m-1][0] = 1;
		for(int i = 1; i < m; i++) mat[i-1][i] = 1;
//		for(int i = 0; i < m; i++) System.out.println(Arrays.toString(mat[i]));
		mat = matPow(mat, n-m+1, 1_000_000_007);
		long sum = 0;
		for(int i = 0; i < m; i++) {
			sum += mat[i][0];
			sum %= 1_000_000_007;
		}
		System.out.println(sum);
	}

	static long[][] matPow(long[][] A, long p, int mod){
		if(p == 1)
			return A;
		if(p % 2 == 1) {
			long[][] B = matPow(A, p-1, mod);
			return multiply(B, A, mod);
		}
		long[][] B = matPow(A, p/2, mod);
		return multiply(B, B, mod);
	}

	static long[][] multiply(long[][] A, long[][] B, int mod){
		long[][] res = new long[A.length][B[0].length];
		if(A[0].length != B.length) System.out.println("Invalid multiplication");
		for(int i = 0; i < A.length; i++) {
			for(int j = 0; j < B[0].length; j++) {
				for(int k = 0; k < B.length; k++) {
					res[i][j] += (A[i][k]*B[k][j])%mod;
					res[i][j] %= mod;
				}
			}
		}
		return res;
	}
}

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

public class q5 {

	static long[][] multiply(long[][] arr1, long[][] arr2, int d1,int d2,int d3,int d4,long mod){
		long[][] arr3=new long[d1][d4];
		for(int i=0;i<d1;i++) {
			for(int j=0;j<d4;j++) {
				for(int k=0;k<d2;k++) {
					arr3[i][j]+=arr1[i][k]*arr2[k][j];
					arr3[i][j]%=mod;
				}
			}
		}
		return arr3;
	}
	static long[][] exp(long[][] arr, long n, int d1,long mod){
		long[][] arr1=new long[d1][d1];
		for(int i=0;i<d1;i++) arr1[i][i]=1;
		if(n==1) return arr;
		if(n>=2) {
			if(n%2==0) {
				long[][] arr3=exp(arr,n/2,d1,mod);
				arr1=multiply(arr3,arr3,d1,d1,d1,d1,mod);
			}
			else {
				long[][] arr3=exp(arr,n/2,d1,mod);
				arr1=multiply(arr3,arr3,d1,d1,d1,d1,mod);
				arr1=multiply(arr,arr1,d1,d1,d1,d1,mod);
			}
		}
		return arr1;
	}

	public static void main(String[] args) throws IOException {

		Reader.init(System.in);
		PrintWriter out=new PrintWriter(System.out);
		StringBuffer output=new StringBuffer("");
		long n=Reader.nextLong();
		int m=Reader.nextInt();
		long mod=1000000007;
		if(n<m) {
			output.append(1);
		}
		else {
			long[][] arr=new long[m][m];
			long[][] arr2=new long[m][1];
			arr2[0][0]=1;
			for(int i=0;i<m;i++) {
				for(int j=0;j<m;j++) {
					if(i==0) {
						if(j==0 || j==m-1) arr[i][j]=1;
					}
					else if(i==j) arr[i][j-1]=1;
				}
			}
			long[][] ans=exp(arr,n,m,mod);
			ans=multiply(ans,arr2,m,m,m,1,mod);
			output.append(ans[0][0]);
		}
		out.write(output.toString());
		out.flush();

	}
}
class NoD{
	int a,b;
	String s;
	NoD(int aa,int bb){
		a=aa;b=bb;
		s=a+" "+b;
	}
	@Override
	public boolean equals(Object o) {
		if(o!=null && o.getClass()==getClass()) {
			NoD c= (NoD) o;
			return c.a==a && c.b==b;
		}
		return false;
	}
	@Override
	public int hashCode() {
		return s.hashCode();
	}
}

class Reader {
    static BufferedReader reader;
    static StringTokenizer tokenizer;

    /** call this method to initialize reader for InputStream */
    static void init(InputStream input) {
        reader = new BufferedReader(
                     new InputStreamReader(input) );
        tokenizer = new StringTokenizer("");
    }

    /** get next word */
    static String nextLine() throws IOException{
    	return reader.readLine();
    }
    static String next() throws IOException {
        while ( ! tokenizer.hasMoreTokens() ) {
            //TODO add check for eof if necessary
            tokenizer = new StringTokenizer(
                   reader.readLine() );
        }
        return tokenizer.nextToken();
    }

    static int nextInt() throws IOException {
        return Integer.parseInt( next() );
    }
    static long nextLong() throws IOException {
        return Long.parseLong( next() );
    }
    static double nextDouble() throws IOException {
        return Double.parseDouble( next() );
    }
}

import java.io.*;
import java.util.*;

import javax.swing.plaf.basic.BasicInternalFrameTitlePane.MaximizeAction;

public class D implements Runnable {
	public static void main (String[] args) {new Thread(null, new D(), "_cf", 1 << 28).start();}

	int MOD = (int)1e9+7;

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		long N = fs.nextLong();
		int M = fs.nextInt();
		if(N < M) {
			System.out.println(1);
			return;
		}

		int[][] matrix = new int[M][M];
		for(int i = 1; i < M; i++) {
			matrix[i][i-1] = 1;
		}
		matrix[0][M-1] = 1;
		matrix[M-1][M-1] = 1;

		int[][] mult = matrixExpo(matrix, N-M+1);
		int[][] base = new int[1][M];
		Arrays.fill(base[0], 1);
		int[][] it = matrixMultiply(base, mult);
		out.println(it[0][M-1]);

		out.close();
	}

	int[][] matrixMultiply(int[][] mat1, int[][] mat2) {
		int[][] res = new int[mat1.length][mat2[0].length];
		for(int i = 0; i < res.length; ++i) {
			for(int j = 0; j < res[i].length; ++j) {
				for(int k = 0; k < mat2.length; ++k) {
					res[i][j] = add(res[i][j], mult(mat1[i][k] , mat2[k][j]));
				}
			}
		}
		return res;
	}

	int[][] matrixExpo(int[][] mat, long expo) {
		if(expo == 0)
			return identity(mat.length);
		if(expo == 1)
			return mat;
		int[][] ret = matrixExpo(mat, expo/2);
		ret = matrixMultiply(ret, ret);
		if(expo % 2 == 1)
			ret = matrixMultiply(ret, mat);
		return ret;
	}

	int[][] identity(int size) {
		int[][] mat = new int[size][size];
		for(int i = 0; i < size; ++i)
			mat[i][i] = 1;
		return mat;
	}

	int add(long a, long b) {
		if(a >= MOD) a -= MOD;
		if(b >= MOD) b -= MOD;
		a += b;
		if(a >= MOD) a -= MOD;
		return (int)a;
	}

	int mult(long a, long b) {
		if(a >= MOD) a -= MOD;
		if(b >= MOD) b -= MOD;
		a *= b;
		if(a >= MOD) a %= MOD;
		return (int)a;
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) throws FileNotFoundException {
			in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}

import java.util.*;

public class Dcode {

    static  int m;
    static  int mod = 1000000007;

    static  long[][] mul(long a[][],long n){
        if(n<=1){
            return a;
        }

        long matrix[][] = new long[m][m];
        for(int i=0;i<m;i++){
            matrix[i][i] = 1;

        }

        while(n>0){
                if((n&1) == 1){
                        matrix = mm(matrix,a);

                }

                    a = mm(a,a);

                        n = n>>1;
        }

         return matrix;

    }

    static long[][] mm(long a[][],long b[][]){
        long c[][] = new long[m][m];

        for(int i=0;i<m;i++){
            for(int j=0;j<m;j++){
                long sum = 0;
                for(int k=0;k<m;k++){
                    sum = (sum + a[i][k]*b[k][j])%mod;
                }

                c[i][j] = sum;
            }
        }

        return c;
    }

    public static  void main(String args[]){

        Scanner s = new Scanner(System.in);
        long n = s.nextLong();
        m = s.nextInt();
        if(n<m){
            System.out.println(1);
            return;
        }
        if(n==m){
            System.out.println(2);
            return;
        }
        long a[][] = new long[m][m];

        a[0][0] = 1;
        a[0][m-1] = 1;
        for(int i=1;i<m;i++){
            a[i][i-1] = 1;
        }

        long ans  = 0;

        long h[][] = mul(a,n-m);

        ans = 2*h[0][0];

        for(int i=1;i<m;i++){
            ans = (ans + h[0][i])%mod;
        }

        System.out.println(ans);

    }
}

import java.io.*;
import java.util.*;

public class Myclass {
    // static ArrayList a[]=new ArrayList[300001];
	static long n,mod =(long) (1e9+7);
	static  int m;
	static long [][] mul(long a[][],long b[][]){
		long ans[][]=new long[m+1][m+1];
		for(int i=0;i<m;i++) {
			for(int j=0;j<m;j++) {
				long sum=0L;
				for(int k=0;k<m;k++) {
					sum=(sum+a[i][k]*b[k][j])%mod;
				}
				ans[i][j]=sum;
			}
		}
		return ans;
	}
     static long pow(long a[][],long l) {
    	 long fi=0L;
    	 long temp[][]=a.clone();
    	 long ans[][]=new long[m+1][m+1];
    	 for(int i=0;i<=m;i++)
    		 ans[i][i]=1L;
    	 while(l>0) {
    		 if(l%2==1) {
    			 ans=mul(ans,temp);
    		 }
    		 temp=mul(temp,temp);
    		 l/=2;
    	 }

    	 for(int i=0;i<=m;i++) {
    		 fi=(fi+ans[0][i])%mod;
    	 }
    	 return fi;
     }
     public static void main(String[] args) throws FileNotFoundException
    {
        InputReader in=new InputReader(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        n=in.nextLong();
        m=in.nextInt();
        long dp[]=new long[m+1];
        for(int i=0;i<m;i++) {
        	dp[i]=1L;
        }
        long a[][]=new long[m+1][m+1];
        a[0][0]=1L;
        a[0][m-1]=1L;
        for(int i=1;i<m;i++) {
        	a[i][i-1]=1L;
        }
        long ans=pow(a,n-m+1);
        pw.println(ans);
        pw.flush();
        pw.close();

    }
    private static void debug(Object... o) {
        System.out.println(Arrays.deepToString(o));
    }
   static class InputReader
        {
        private final InputStream stream;
        private final byte[] buf = new byte[8192];
        private int curChar, snumChars;
        private SpaceCharFilter filter;

        public InputReader(InputStream stream)
        {
            this.stream = stream;
        }
        public int snext()
        {
            if (snumChars == -1)
                throw new InputMismatchException();
            if (curChar >= snumChars)
            {
                curChar = 0;
                try
                {
                    snumChars = stream.read(buf);
                }

                catch (IOException e)
                {
                    throw new InputMismatchException();
                }

                if (snumChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public int nextInt()
        {
            int c = snext();
            while (isSpaceChar(c))
            {
                c = snext();
            }
            int sgn = 1;
            if (c == '-')
            {
                sgn = -1;
                c = snext();
            }
            int res = 0;
            do
            {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = snext();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong()
        {
            int c = snext();
            while (isSpaceChar(c))
            {
                c = snext();
            }
            int sgn = 1;
            if (c == '-')
            {
                sgn = -1;
                c = snext();
            }
            long res = 0;
            do
            {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = snext();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public int[] nextIntArray(int n)
        {
            int a[] = new int[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = nextInt();
            }
            return a;
        }
        static class tri implements Comparable<tri> {
            int p, c, l;

            tri(int p, int c, int l) {
                this.p = p;
                this.c = c;
                this.l = l;
            }

            public int compareTo(tri o) {
                return Integer.compare(l, o.l);
            }
        }

        public String readString()
        {
            int c = snext();
            while (isSpaceChar(c))
            {
                c = snext();
            }
            StringBuilder res = new StringBuilder();
            do
            {
                res.appendCodePoint(c);
                c = snext();
            } while (!isSpaceChar(c));
            return res.toString();
        }

        public String nextLine()
        {
            int c = snext();
            while (isSpaceChar(c))
                c = snext();
            StringBuilder res = new StringBuilder();
            do
            {
                res.appendCodePoint(c);
                c = snext();
            } while (!isEndOfLine(c));
            return res.toString();
        }

        public boolean isSpaceChar(int c)
        {
            if (filter != null)
                return filter.isSpaceChar(c);
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        private boolean isEndOfLine(int c)
        {
            return c == '\n' || c == '\r' || c == -1;
        }

        public interface SpaceCharFilter
        {
            public boolean isSpaceChar(int ch);
        }
    }
   public static long modularExponentiation(long x,long n,long M)
   {
       long result=1;
       while(n>0)
       {
           if(n % 2 ==1)
               result=(result%M * x%M)%M;
           x=(x%M * x%M)%M;
           n=n/2;
       }
       return result;
   }

   public static long modInverse(int A,int M)
   {
       return modularExponentiation(A,M-2,M);
   }

   public static long modInverse(long A,long M)
   {
       return modularExponentiation(A,M-2,M);
   }
    static class pair implements Comparable<pair>{
        Long x;
        Long y;

        pair(long x,long w){
            this.x=x;
            this.y=w;
        }

		public int compareTo(pair o) {
                int result = x.compareTo(o.x);
                if(result==0)
                    result = y.compareTo(o.y);

            return result;
            }
         public String toString(){
            return (x+" "+y);
        }
  }
    static class query{
    	Double x;
    	Integer y;
    	query(double x,int y){
    		this.x=x;
    		this.y=y;
    	}
    }

}

	import java.util.*;
	import java.io.*;

			public class codeforces
			{
				public static long M = 1000000007;
				public static TreeSet<Integer> adj[];

				public static void main(String[] args)
				{
					InputReader in = new InputReader(System.in);
					PrintWriter pw = new PrintWriter(System.out);
					long N = in.nextLong();
					int m = in.nextInt();
					long[][] f = new long[m][1];
					for(int i=0;i<m;i++)
						f[i][0] = 1;
					long[][] mat = new long[m][m];
					mat[0][0] = 1;
					mat[0][m-1] = 1;
					for(int i=1;i<m;i++)
						mat[i][i-1] = 1;
					mat = matrixpower(mat, N-m+1, M);
					f = matrixmultiply(mat, f, M);
					pw.print(f[0][0]);
					pw.flush();
					pw.close();
				}

				public static long[][] matrixpower(long[][] mat, long n, long p)
				{
					int r = mat.length;
					long[][] ans = new long[r][r];

					for(int i=0;i<r;i++)
						ans[i][i] = 1;

					while(n > 0)
					{
						if(n%2 == 1)
							ans = matrixmultiply(ans, mat, p);
						mat = matrixmultiply(mat, mat, p);
						n /= 2;
					}

					return ans;
				}

				public static long[][] matrixmultiply(long[][] M1, long[][] M2, long p)
				{
					int m1 = M1.length, m2 = M2[0].length;
					long[][] ans = new long[m1][m2];

					for(int i=0;i<m1;i++)
					{
						for(int j=0;j<m2;j++)
						{
							for(int k=0;k<M2.length;k++)
							{
								ans[i][j] += M1[i][k]*M2[k][j];
								if(ans[i][j] >= p)
									ans[i][j] %= p;
							}
						}
						//System.out.println(Arrays.toString(ans[i]));
					}
					return ans;
				}

				public static long prime(long nth) {

				    long num, count, i;
				    num=1;
				    count=0;

				    while (count < nth){
				      num=num+1;
				      for (i = 2; i <= num; i++){ //Here we will loop from 2 to num
				        if (num % i == 0) {
				          break;
				        }
				      }
				      if ( i == num){//if it is a prime number
				        count = count+1;
				      }
				    }
				    return num;
				  }

				public static int[] suffle(int[] a,Random gen)
				{
					int n = a.length;
					for(int i=0;i<n;i++)
					{
						int ind = gen.nextInt(n-i)+i;
						int temp = a[ind];
						a[ind] = a[i];
						a[i] = temp;
					}
					return a;
				}

				public static long modularExponentiation(long x,long n,long M)
				{
				    long result=1;
				    while(n>0)
				    {
				        if(n % 2 ==1)
				            result=(result * x)%M;
				        x=(x*x)%M;
				        n=n/2;
				    }
				    return result;
				}

				public static long modInverse(long A,long M)
				{
				    return modularExponentiation(A,M-2,M);
				}

				public static int BinarySearch_l(long[] a, long k)
				{
					int n = a.length;
					int i = 0, j = n-1;
					int mid = 0;

					if(k - a[n-1] > 0)
						return n;
					else
					{
						while(j - i > 0)
						{
							mid = (i+j)/2;

							if(k - a[mid] > 0)
								i = mid + 1;
							else
								j = mid;
						}
					}

					return i;
				}

				public static int BinarySearch_r(long[] a, long k)
				{
					int n = a.length;
					int i = 0, j = n-1;
					int mid = 0;

					if(k - a[0] < 0)
						return -1;
					else
					{
						while(j - i > 0)
						{
							mid = (int)Math.ceil((double)(i+j)/2);

							if(k - a[mid] >= 0)
								i = mid;
							else
								j = mid - 1;
						}
					}

					return i;
				}
				public static long fact(long n, long M)
				{
					long ans = 1;

					for(long i=n;i>0;i--)
					{
						ans = (ans*i)%M;
					}

					return ans;
				}

			/*	public static void DFS(int sourse)
				{
					int count = 0;
					visited[sourse] = true;

					for(int u : adj[sourse])
					{
						if(!visited[u])
						{
							DFS(u);
						}
					}

				}*/

				public static ArrayList Divisors(int n)
				{
				    ArrayList<Integer> div = new ArrayList<>();

				    for (int i=1; i<=Math.sqrt(n); i++)
				    {
				        if (n%i == 0)
				        {
				        	div.add(i);

				            if(n/i != i)
				            	div.add(n/i);
				        }
				    }
				    return div;
				}

				public static long GCD(long a,long b)
				{
					if(b==0)
						return a;
					else
						return GCD(b,a%b);
				}

				public static long LCM(long a,long b)
				{
					return (a*b)/GCD(a, b);
				}

				static class pair implements Comparable<pair>
				{
					Integer x, y;
					pair(int x,int y)
					{
						this.x=x;
						this.y=y;
					}

					public int compareTo(pair o) {
						int result = x.compareTo(o.x);
						if(result==0)
							result = y.compareTo(o.y);

						return result;
					}

					public String toString()
					{
						return x+" "+y;
					}

					public boolean equals(Object o)
					{
						if (o instanceof pair)
					    {
							pair p = (pair)o;
							return p.x - x == 0 && p.y - y == 0 ;
						}
						return false;
					}

					public int hashCode()
					{
						return new Long(x).hashCode()*31 + new Long(y).hashCode();
					}
				}

				static class InputReader
				{

					private final InputStream stream;
					private final byte[] buf = new byte[8192];
					private int curChar, snumChars;
					private SpaceCharFilter filter;

					public InputReader(InputStream stream)
					{
						this.stream = stream;
					}

					public int snext()
					{
						if (snumChars == -1)
							throw new InputMismatchException();
						if (curChar >= snumChars)
						{
							curChar = 0;
							try
							{
								snumChars = stream.read(buf);
							}
							catch (IOException e)
							{
								throw new InputMismatchException();
							}
							if (snumChars <= 0)
								return -1;
						}
						return buf[curChar++];
					}

					public int nextInt()
				    {
						int c = snext();
						while (isSpaceChar(c))
						{
							c = snext();
						}
						int sgn = 1;
						if (c == '-')
					    {
							sgn = -1;
							c = snext();
						}
						int res = 0;
						do
						{
							if (c < '0' || c > '9')
								throw new InputMismatchException();
							res *= 10;
							res += c - '0';
							c = snext();
						} while (!isSpaceChar(c));
						return res * sgn;
					}

					public long nextLong()
				    {
						int c = snext();
						while (isSpaceChar(c))
						{
							c = snext();
						}
						int sgn = 1;
						if (c == '-')
						{
							sgn = -1;
							c = snext();
						}
						long res = 0;
						do
						{
							if (c < '0' || c > '9')
								throw new InputMismatchException();
							res *= 10;
							res += c - '0';
							c = snext();
						} while (!isSpaceChar(c));
						return res * sgn;
					}

					public int[] nextIntArray(int n)
					{
						int a[] = new int[n];
						for (int i = 0; i < n; i++)
						{
							a[i] = nextInt();
						}
						return a;
					}

					public String readString()
				    {
						int c = snext();
						while (isSpaceChar(c))
						{
							c = snext();
						}
						StringBuilder res = new StringBuilder();
						do
						{
							res.appendCodePoint(c);
							c = snext();
						} while (!isSpaceChar(c));
						return res.toString();
					}

					public String nextLine()
					{
						int c = snext();
						while (isSpaceChar(c))
							c = snext();
						StringBuilder res = new StringBuilder();
						do
						{
							res.appendCodePoint(c);
							c = snext();
						} while (!isEndOfLine(c));
						return res.toString();
					}

					public boolean isSpaceChar(int c)
					{
						if (filter != null)
							return filter.isSpaceChar(c);
						return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
					}

					private boolean isEndOfLine(int c)
					{
						return c == '\n' || c == '\r' || c == -1;
					}

					public interface SpaceCharFilter
				    {
						public boolean isSpaceChar(int ch);
					}
				}

				static class CodeX {
		        public static void sort(long arr[]) {
		            merge_sort(arr, 0, arr.length - 1);
		        }

		        private static void merge_sort(long A[], long start, long end) {
		            if (start < end) {
		                long mid = (start + end) / 2;
		                merge_sort(A, start, mid);
		                merge_sort(A, mid + 1, end);
		                merge(A, start, mid, end);
		            }

		        }

		        private static void merge(long A[], long start,long mid, long end) {
		            long p = start, q = mid + 1;
		            long Arr[] = new long[(int)(end - start + 1)];
		            long k = 0;

		            for (int i = (int)start; i <= end; i++) {
		                if (p > mid)
		                    Arr[(int)k++] = A[(int)q++];

		                else if (q > end)
		                    Arr[(int)k++] = A[(int)p++];

		                else if (A[(int)p] < A[(int)q])
		                    Arr[(int)k++] = A[(int)p++];

		                else
		                    Arr[(int)k++] = A[(int)q++];
		            }
		            for (int i = 0; i < k; i++) {
		                A[(int)start++] = Arr[i];
		            }

		        }

		    }
			}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DMagicGems solver = new DMagicGems();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems {
        private long MOD = (int) 1e9 + 7;

        private long[][] matrixMult(long[][] A, long[][] B) {
            if (A[0].length != B.length) {
                throw new IllegalArgumentException();
            }
            int n = A.length;
            int p = A[0].length;
            int m = B[0].length;

            long[][] C = new long[n][m];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    for (int k = 0; k < p; k++) {
                        C[i][j] += A[i][k] * B[k][j];
                        if (C[i][j] >= MOD) {
                            C[i][j] %= MOD;
                        }
                    }
                }
            }
            return C;
        }

        private long[][] matrixPow(long[][] A, long n) {
            if (n < 1) {
                throw new IllegalArgumentException();
            }
            if (n == 1) {
                return A;
            }
            long[][] B = matrixPow(A, n / 2);
            B = matrixMult(B, B);
            if (n % 2 == 1) {
                B = matrixMult(B, A);
            }
            return B;
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long n = in.nextLong();
            int m = in.nextInt();

            if (m > n) {
                out.println(1);
                return;
            }

            long[][] M = new long[m][m];
            M[0][0] = 1;
            M[0][m - 1] = 1;
            for (int i = 1; i < m; i++) {
                M[i][i - 1] = 1;
            }
            M = matrixPow(M, n - m + 1);

            long x_n = 0;
            for (int i = 0; i < m; i++) {
                x_n = (x_n + M[0][i]) % MOD;
            }
            out.println(x_n);
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }
}

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

	static int mod = 7+(int)1e9;

	static int[][] matMul(int[][] A, int[][] B, int p, int q, int r)
	{
		int[][] C = new int[p][r];
		for(int i = 0; i < p; ++i)
			for(int j = 0; j < r; ++j)
				for(int k = 0; k < q; ++k)
				{
					C[i][j] += (int)((1l* A[i][k] * B[k][j])%mod);
					C[i][j] %= mod;
				}
		return C;
	}

	static int[][] matPow(int[][] base, long p)
	{
		int n = base.length;
		int[][] ans = new int[n][n];
		for(int i = 0; i < n; i++)
			ans[i][i] = 1;
		while(p > 0)
		{
			if((p & 1) == 1)
				ans = matMul(ans, base, n, n, n);
			base = matMul(base, base, n, n, n);
			p >>= 1;
		}
		return ans;
	}

	static int F(long n,int m)
	{
		int[][] M =new int[m][m];
		for(int i = 1;i<m;i++)M[i][i-1] = 1;
		M[0][m-1] = M[m-1][m-1] = 1;
		int[][] base = new int[1][m];
		Arrays.fill(base[0], 1);
		int g = matMul(base,matPow(M, n-m+1), 1, m, m)[0][m-1]%mod;
		return g%mod;
	}

	public static void main(String[] args) throws Throwable {
		Scanner sc = new Scanner(System.in);
		long n = sc.nextLong();
		int m = sc.nextInt();
		System.out.println(F(n,m));
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s) {
			br = new BufferedReader(new InputStreamReader(s));
		}

		public Scanner(String file) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(file));
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		public long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public String nextLine() throws IOException {
			return br.readLine();
		}

		public double nextDouble() throws IOException {
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if (x.charAt(0) == '-') {
				neg = true;
				start++;
			}
			for (int i = start; i < x.length(); i++)
				if (x.charAt(i) == '.') {
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				} else {
					sb.append(x.charAt(i));
					if (dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg ? -1 : 1);
		}

		public int[] nexIntArray() throws Throwable {
			st = new StringTokenizer(br.readLine());
			int[] a = new int[st.countTokens()];
			for (int i = 0; i < a.length; i++)
				a[i] = nextInt();
			return a;
		}

		public boolean ready() throws IOException {
			return br.ready();
		}

		public boolean hasNext() throws Throwable {
			return br.ready() || st.hasMoreTokens();
		}
	}

}

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class EducationalRound60D {

	public static long mod = (long)1e9+7;

	public static void solve() {
		long n = s.nextLong();
		int m = s.nextInt();
		if(n < m) {
			out.println(1);
			return;
		}
		long[][] A = new long[m][m];
		A[0][0] = 1;
		A[0][m - 1] = 1;
		int pos = 0;
		for(int i = 1; i < m; i++) {
			A[i][pos++] = 1;
		}
		long[][] ans = fast(A, n - (long)m + 1L);
		long sum = 0;
		for(int i = 0; i < m; i++) {
			sum += ans[0][i];
			if(sum >= mod) sum -= mod;
		}
		out.println(sum);
	}

	public static long[][] fast(long[][] A, long n){
		if(n == 1) {
			return A;
		}
		long[][] ans = fast(A, n/2L);
		ans = mult(ans, ans);
		if((n&1L) == 1) {
			ans = mult(ans, A);
		}
		return ans;
	}

	public static long[][] mult(long[][] A, long[][] B){
		int n = A.length;
		long[][] ans = new long[n][n];
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < n; j++) {
				long sum = 0;
				for(int k = 0; k < n; k++) {
					sum += (A[i][k] * B[k][j])%mod;
					if(sum >= mod) sum -= mod;
				}
				ans[i][j] = sum;
			}
		}
		return ans;
	}

	public static void main(String[] args) {
		out = new PrintWriter(new BufferedOutputStream(System.out));
		s = new FastReader();
		solve();
		out.close();
	}

	public static FastReader s;
	public static PrintWriter out;

	public static class FastReader {
		BufferedReader br;
		StringTokenizer st;

		public FastReader() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

		int nextInt() {
			return Integer.parseInt(next());
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}

		long nextLong() {
			return Long.parseLong(next());
		}

		String nextLine() {
			String str = "";
			try {
				str = br.readLine();
			} catch (Exception e) {
				e.printStackTrace();
			}
			return str;
		}
	}

}

import java.io.*;
import java.util.*;
import java.math.*;
import java.awt.Point;

public class Main {
	//static final long MOD = 998244353L;
	//static final long INF = -1000000000000000007L;
	static final long MOD = 1000000007L;
	//static final int INF = 1000000007;

	public static void main(String[] args) {
		FastScanner sc = new FastScanner();
		PrintWriter pw = new PrintWriter(System.out);
		long N = sc.nl();
		int M = sc.ni();
		//Relationship is g(i)=g(i-1)+g(i-M)

		long[][] mat = new long[M][M];
		mat[0][0] = 1;
		mat[0][M-1] = 1;
		for (int i = 1; i < M; i++) {
			mat[i][i-1] = 1;
		}

		Matrix MATRIX = new Matrix(mat,MOD);
		if (N < M) {
			pw.println(1);
		} else {
			//pw.println(Arrays.deepToString(MATRIX.matrix));
			long[][] pow = MATRIX.matpower(MATRIX.matrix,N-M+1);
			//pw.println(Arrays.deepToString(pow));
			//g(m-1), g(m-2),...,g(0) are all equal to 1.
			long ans = 0;
			for (int i = 0; i < M; i++) {
				ans += pow[0][i];
				ans %= MOD;
			}
			pw.println(ans);
		}
		pw.close();
 	}

	//Useful in matrix multiplacation for linear relationships
	static class Matrix {
		public long[][] matrix;
		public long MOD;
		public int M;

		public Matrix(long[][] matrix, long MOD) {
			this.matrix = matrix;
			this.MOD = MOD;
			M = matrix.length;
		}

		public long[][] matmul(long[][] a, long[][] b) {
	        long[][] ans = new long[M][M];
	        for (int i = 0; i < M; i++) {
	            for (int j = 0; j < M; j++) {
	                for (int k = 0; k < M; k++) {
	                    ans[i][j] += a[i][k]*b[k][j];
	                    ans[i][j] %= MOD;
	                }
	            }
	        }
	        return ans;
		}

		public long[][] matpower(long[][] mat, long pow) {
			long[][] ans = new long[M][M];
			for (int i = 0; i < M; i++)
				ans[i][i] = 1;
			while (pow > 0) {
				if (pow % 2 == 1) {
					ans = matmul(ans,mat);
				}
				pow /= 2;
				mat = matmul(mat,mat);
			}
			return ans;
		}
	}

    public static int[][] sort(int[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    int[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<int[]>() {
			  @Override
        	  public int compare(int[] arr1, int[] arr2) {
				  //return arr1[0]-arr2[0]; //ascending order
				  if (arr1[0] != arr2[0]) {
					  return arr1[0]-arr2[0];
				  } else {
					  return arr1[1]-arr2[1];
				  }
	          }
		});
		return array;
	}

    public static long[][] sort(long[][] array) {
    	//Sort an array (immune to quicksort TLE)
		Random rgen = new Random();
		for (int i = 0; i < array.length; i++) {
		    int randomPosition = rgen.nextInt(array.length);
		    long[] temp = array[i];
		    array[i] = array[randomPosition];
		    array[randomPosition] = temp;
		}
		Arrays.sort(array, new Comparator<long[]>() {
			  @Override
        	  public int compare(long[] arr1, long[] arr2) {
				  return 0;
	          }
		});
		return array;
	}

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException  e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int ni() {
            return Integer.parseInt(next());
        }

        long nl() {
            return Long.parseLong(next());
        }

        double nd() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

/*Author: Satyajeet Singh, Delhi Technological University*/
import java.io.*;
import java.util.*;
import java.text.*;
import java.lang.*;

public class Main {
/*********************************************Constants******************************************/
    static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static long mod=(long)1e9+7;
    static long mod1=998244353;
    static boolean sieve[];
    static ArrayList<Integer> primes;
    static ArrayList<Long> factorial;
    static HashSet<Integer> graph[];
/****************************************Solutions Begins*****************************************/
    static long mmod=mod*mod;

    static long[][] matmul(long A[][],long B[][]){
        int n=A.length;
        int p=A[0].length;
        int m=B[0].length;
        long ans[][]=new long[n][m];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                for(int k=0;k<p;k++){
                    long aa=(A[i][k]*B[k][j])%mod;
                    ans[i][j]=ans[i][j]+aa;;
                    if(ans[i][j]>=mmod){
                        ans[i][j]-=mmod;
                    }
                    if(ans[i][j]>=mod){
                        ans[i][j]-=mod;
                    }
                }
            }
        }
        return ans;
    }
    static long[][] matexpo(long A[][],long exp){
        if(exp==1){
            return A;
        }
        long B[][]=matexpo(A,exp/2);
        if(exp%2==0){
            return matmul(B,B);
        }
        else{
            return matmul(matmul(B,B),A);
        }
    }
    public static void main (String[] args) throws Exception {
        String st[]=br.readLine().split(" ");
        long n=Long.parseLong(st[0]);
        int m=Integer.parseInt(st[1]);
        if(m>n){
            out.println(1);
            out.flush();
            return ;
        }
        long mat[][]=new long[m][m];
        long F[][]=new long[m][1];
        for(int i=0;i<m;i++){
            F[i][0]=1;
        }
        F[m-1][0]=2;

        for(int i=0;i<m-1;i++){
            mat[i][i+1]=1;
        }
        mat[m-1][m-1]=1;
        mat[m-1][0]=1;
        long T[][]=matexpo(mat,n-1);
        long A[][]=matmul(T,F);
       // debug(mat);
        out.println(A[0][0]);
/****************************************Solutions Ends**************************************************/
        out.flush();
        out.close();
    }
/****************************************Template Begins************************************************/
/***************************************Precision Printing**********************************************/
    static void printPrecision(double d){
        DecimalFormat ft = new DecimalFormat("0.000000");
        out.println(ft.format(d));
    }
/******************************************Graph*********************************************************/
    static void Makegraph(int n){
        graph=new HashSet[n];
        for(int i=0;i<n;i++){
            graph[i]=new HashSet<>();
        }
    }
    static void addEdge(int a,int b){
        graph[a].add(b);
    }

/*********************************************PAIR********************************************************/
    static class PairComp implements Comparator<Pair>{
        public int compare(Pair p1,Pair p2){
            if(p1.u>p2.u){
                return 1;
            }
            else if(p1.u<p2.u){
                return -1;
            }
            else{
                return p1.v-p2.v;
            }
        }
    }
    static class Pair implements Comparable<Pair> {
        int u;
        int v;
        int index=-1;
        public Pair(int u, int v) {
            this.u = u;
            this.v = v;
        }

        public int hashCode() {
            int hu = (int) (u ^ (u >>> 32));
            int hv = (int) (v ^ (v >>> 32));
            return 31 * hu + hv;
        }

        public boolean equals(Object o) {
            Pair other = (Pair) o;
            return u == other.u && v == other.v;
        }

        public int compareTo(Pair other) {
            if(index!=other.index)
                return Long.compare(index, other.index);
            return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
        }

        public String toString() {
            return "[u=" + u + ", v=" + v + "]";
        }
    }

    static class PairCompL implements Comparator<Pairl>{
        public int compare(Pairl p1,Pairl p2){
            if(p1.u>p2.u){
                return 1;
            }
            else if(p1.u<p2.u){
                return -1;
            }
            else{
                return 0;
            }
        }
    }
    static class Pairl implements Comparable<Pair> {
            long u;
            long v;
            int index=-1;
            public Pairl(long u, long v) {
                this.u = u;
                this.v = v;
            }

            public int hashCode() {
                int hu = (int) (u ^ (u >>> 32));
                int hv = (int) (v ^ (v >>> 32));
                return 31 * hu + hv;
            }

            public boolean equals(Object o) {
                Pair other = (Pair) o;
                return u == other.u && v == other.v;
            }

            public int compareTo(Pair other) {
                if(index!=other.index)
                    return Long.compare(index, other.index);
                return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
            }

            public String toString() {
                return "[u=" + u + ", v=" + v + "]";
            }
        }
/*****************************************DEBUG***********************************************************/
    public static void debug(Object... o) {
        System.out.println(Arrays.deepToString(o));
    }
/************************************MODULAR EXPONENTIATION***********************************************/
    static long modulo(long a,long b,long c) {
        long x=1;
        long y=a;
        while(b > 0){
            if(b%2 == 1){
                x=(x*y)%c;
            }
            y = (y*y)%c; // squaring the base
            b /= 2;
        }
        return  x%c;
    }
/********************************************GCD**********************************************************/
    static long gcd(long x, long y)
    {
        if(x==0)
            return y;
        if(y==0)
            return x;
        long r=0, a, b;
        a = (x > y) ? x : y; // a is greater number
        b = (x < y) ? x : y; // b is smaller number
        r = b;
        while(a % b != 0)
        {
            r = a % b;
            a = b;
            b = r;
        }
        return r;
    }
/******************************************SIEVE**********************************************************/
    static void sieveMake(int n){
        sieve=new boolean[n];
        Arrays.fill(sieve,true);
        sieve[0]=false;
        sieve[1]=false;
        for(int i=2;i*i<n;i++){
            if(sieve[i]){
                for(int j=i*i;j<n;j+=i){
                    sieve[j]=false;
                }
            }
        }
        primes=new ArrayList<Integer>();
        for(int i=0;i<n;i++){
            if(sieve[i]){
                primes.add(i);
            }
        }
    }
/********************************************End***********************************************************/
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.PrintStream;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Rustam Musin (t.me/musin_acm)
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        DMagicheskieKamni solver = new DMagicheskieKamni();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicheskieKamni {
        int mod = (int) 1e9 + 7;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            long n = in.readLong();
            int m = in.readInt();
            out.print(new Solve().solve(n, m));
            new Test().test();
        }

        int add(int a, int b) {
            a += b;
            if (a >= mod) {
                a -= mod;
            }
            return a;
        }

        int mul(int a, int b) {
            long c = a * (long) b;
            return (int) (c % mod);
        }

        int[][] mul(int[][] a, int[][] b) {
            int n = a.length;
            int m = b[0].length;
            int[][] c = new int[n][m];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    for (int k = 0; k < a[i].length; k++) {
                        c[i][j] = add(c[i][j], mul(a[i][k], b[k][j]));
                    }
                }
            }
            return c;
        }

        int[][] pow(int[][] a, long p) {
            if (p == 1) {
                return a;
            }
            int[][] res = pow(a, p / 2);
            res = mul(res, res);
            if (p % 2 == 1) {
                res = mul(res, a);
            }
            return res;
        }

        class Test {
            void test() {
                for (int n = 1; n <= 10; n++) {
                    for (int m = 2; m <= 10; m++) {
                        int solve = new Solve().solve(n, m);
                        int naive = new Naive().solve(n, m);
                        if (solve != naive) {
                            System.err.println(n + " " + m);
                            System.err.println("S " + solve);
                            System.err.println("N " + naive);
                            System.err.println("--");
                        }
                    }
                }
            }

        }

        class Solve {
            int solve(long n, int m) {
                int[][] first = new int[m][m];
                for (int i = 0; i < m; i++) {
                    first[i][(i + 1) % m] = 1;
                }
                first[m - 1][m - 1] = 1;

                int[][] multed = pow(first, n);

                int answer = 0;
                for (int i = 0; i < m; i++) {
                    answer = add(answer, multed[0][i]);
                }

                return answer;
            }

        }

        class Naive {
            int m;
            int[] dp;

            int solve(int n, int m) {
                this.m = m;
                this.dp = new int[n + 1];
                Arrays.fill(dp, -1);
                return dfs(n);
            }

            int dfs(int elements) {
                if (dp[elements] != -1) {
                    return dp[elements];
                }
                if (elements == 0) {
                    return 1;
                }
                int ans = dfs(elements - 1);
                if (elements >= m) {
                    ans += dfs(elements - m);
                }
                return dp[elements] = ans;
            }

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void close() {
            writer.close();
        }

        public void print(int i) {
            writer.print(i);
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int readInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long readLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.util.Map;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.HashMap;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author prakharjain
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        DMagicGems_dac solver = new DMagicGems_dac();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems_dac {
        long[] dp;
        long n;
        int m;
        int mod = 1000000007;
        Map<Long, Long> map = new HashMap<>();

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            n = in.nextLong();
            m = in.nextInt();

            dp = new long[1000];

            dp[0] = 1;

            for (int i = 1; i < 1000; i++) {
                dp[i] += dp[i - 1];
                dp[i] %= mod;

                if (i >= m) {
                    dp[i] += dp[i - m];
                    dp[i] %= mod;
                }

                if (i == m - 1) {
                    dp[i]++;
                    dp[i] %= mod;
                }
            }

            if (n <= 1000) {
                out.println(dp[(int) n - 1]);
                return;
            }

            out.print(cal(n));
        }

        long cal(long n) {
            if (n <= 1000) {
                return dp[(int) n - 1];
            }

            if (map.containsKey(n)) {
                return map.get(n);
            }

            long mid = n / 2;

            long ans = 0;

            long val1 = cal(mid);
            long val2 = cal(n - mid);

            ans += (val1 * val2) % mod;

            for (int i = m - 1; i > 0; i--) {
                val1 = cal(mid - i);
                val2 = cal(n - mid - (m - i));

                ans += (val1 * val2) % mod;
                ans %= mod;
            }

            map.put(n, ans);

            return ans;
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void close() {
            writer.close();
        }

        public void print(long i) {
            writer.print(i);
        }

        public void println(long i) {
            writer.println(i);
        }

    }
}

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MOD = 1000000007;

    // After writing solution, quick scan for:
    //   array out of bounds
    //   special cases e.g. n=1?
    //
    // Big numbers arithmetic bugs:
    //   int overflow
    //   sorting, or taking max, after MOD
    void solve() throws IOException {
        long[] NM = rll(2);
        long N = NM[0];
        int M = (int) NM[1];
        pw.println(helper(N, M));
    }

    Map<Long, Long> memo = new HashMap<>();
    long helper(long N, int M) {
        if (N == M) return 2;
        if (N < 0) return 0;
        if (N < M) return 1;
        if (memo.containsKey(N)) return memo.get(N);
        long ans = 0;
        long mid = N / 2;
        long left = helper(mid, M);  // all in left
        long right = helper(N - mid, M);  // all in right
        ans = (ans + left * right) % MOD;
        // middle two are 0s
        for (int i = 1; i <= M-1; i++) {  // i is how many are in left half
            int j = M-i;
            long l = helper(mid - i, M);
            long r = helper(N-mid - j, M);
            ans = (ans + l * r) % MOD;
        }
        memo.put(N, ans);
        return ans;
    }

    // Template code below

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.solve();
        m.close();
    }

    void close() throws IOException {
        pw.flush();
        pw.close();
        br.close();
    }

    int ri() throws IOException {
        return Integer.parseInt(br.readLine().trim());
    }

    long rl() throws IOException {
        return Long.parseLong(br.readLine().trim());
    }

    int[] ril(int n) throws IOException {
        int[] nums = new int[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            int x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    long[] rll(int n) throws IOException {
        long[] nums = new long[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            long x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    int[] rkil() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return ril(x);
    }

    long[] rkll() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return rll(x);
    }

    char[] rs() throws IOException {
        return br.readLine().toCharArray();
    }

    void sort(int[] A) {
        Random r = new Random();
        for (int i = A.length-1; i > 0; i--) {
            int j = r.nextInt(i+1);
            int temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }
        Arrays.sort(A);
    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author prakharjain
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        DMagicGems solver = new DMagicGems();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems {
        int mod = 1000000007;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            long n = in.nextLong();
            int m = in.nextInt();
            long[] dp = new long[m];

            dp[0] = 1;

            for (int i = 1; i < m; i++) {
                dp[i] += dp[i - 1];
                dp[i] %= mod;

                if (i >= m) {
                    dp[i] += dp[i - m];
                    dp[i] %= mod;
                }

                if (i == m - 1) {
                    dp[i]++;
                    dp[i] %= mod;
                }
            }

            if (n <= m) {
                out.println(dp[(int) n - 1]);
                return;
            }

            MatrixExpo me = new MatrixExpo(m);

            long[][] base = new long[m][m];

            base[0][0] = 1;
            base[0][m - 1] = 1;

            for (int i = 1; i < m; i++) {
                base[i][i - 1] = 1;
            }

            base = me.matrixPower(base, n - m, mod);

            long ans = 0;

            for (int i = 0; i < m; i++) {
                ans += (base[0][i] * dp[m - 1 - i]) % mod;
                ans %= mod;
            }

            out.println(ans);
        }

        class MatrixExpo {
            int n;

            public MatrixExpo(int n) {
                this.n = n;
            }

            long[][] matrixPower(long[][] base, long pow, long mod) {
                long[][] ans = new long[n][n];

                for (int i = 0; i < n; i++)
                    ans[i][i] = 1;

                while (pow != 0) {
                    if ((pow & 1) != 0) ans = multiplyMatrix(ans, base, mod);

                    base = multiplyMatrix(base, base, mod);

                    pow >>= 1;
                }

                return ans;
            }

            long[][] multiplyMatrix(long[][] m, long[][] m2, long mod) {
                long[][] ans = new long[n][n];

                for (int i = 0; i < n; i++)
                    for (int k = 0; k < n; k++) {
                        for (int j = 0; j < n; j++) {
                            ans[i][j] += (m[i][k] * m2[k][j]) % mod;
                            ans[i][j] %= mod;
                        }
                    }

                return ans;
            }

        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void close() {
            writer.close();
        }

        public void println(long i) {
            writer.println(i);
        }

    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author prakharjain
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        DMagicGems solver = new DMagicGems();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems {
        int mod = 1000000007;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            long n = in.nextLong();
            int m = in.nextInt();
            long[] dp = new long[m];

            dp[0] = 1;

            for (int i = 1; i < m; i++) {
                dp[i] += dp[i - 1];
                dp[i] %= mod;

                if (i >= m) {
                    dp[i] += dp[i - m];
                    dp[i] %= mod;
                }

                if (i == m - 1) {
                    dp[i]++;
                    dp[i] %= mod;
                }
            }

            if (n <= m) {
                out.println(dp[(int) n - 1]);
                return;
            }

            MatrixExpo me = new MatrixExpo(m);

            long[][] base = new long[m][m];

            base[0][0] = 1;
            base[0][m - 1] = 1;

            for (int i = 1; i < m; i++) {
                base[i][i - 1] = 1;
            }

            base = me.matrixPower(base, n - m, mod);

            long ans = 0;

            for (int i = 0; i < m; i++) {
                ans += (base[0][i] * dp[m - 1 - i]) % mod;
                ans %= mod;
            }

            out.println(ans);
        }

        class MatrixExpo {
            int n;

            public MatrixExpo(int n) {
                this.n = n;
            }

            long[][] matrixPower(long[][] base, long pow, long mod) {
                long[][] ans = new long[n][n];

                for (int i = 0; i < n; i++)
                    ans[i][i] = 1;

                while (pow != 0) {
                    if ((pow & 1) != 0) ans = multiplyMatrix(ans, base, mod);

                    base = multiplyMatrix(base, base, mod);

                    pow >>= 1;
                }

                return ans;
            }

            long[][] multiplyMatrix(long[][] m, long[][] m2, long mod) {
                long[][] ans = new long[n][n];

                for (int i = 0; i < n; i++)
                    for (int j = 0; j < n; j++) {
                        ans[i][j] = 0;
                        for (int k = 0; k < n; k++) {
                            ans[i][j] += (m[i][k] * m2[k][j]) % mod;
                            ans[i][j] %= mod;
                        }
                    }

                return ans;
            }

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void close() {
            writer.close();
        }

        public void println(long i) {
            writer.println(i);
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }
}

// Concept : hackerearth matrix exponentiation
import java.util.*;
import java.io.*;
public class s3
{
    static int mod=1000000007;
    static void multiply(long mat1[][], long mat2[][],int m) {
               long res[][] = new long[m][m];

                int i, j, k;

        for (i = 0; i < m; i++)
            for (j = 0; j < m; j++) {
                     res[i][j] = 0;
                for (k = 0; k < m; k++)
                    res[i][j] =(res[i][j]+ mat1[i][k]* mat2[k][j])%mod;
            }
         for(i=0;i<m;i++)
           for( j=0;j<m;j++)
               mat1[i][j]=res[i][j];
    }
    static long pow(long mat[][],long b,int m){

                    long res[][]= new long[m][m];

                    for(int i=0;i<m;i++)
                      for(int j=0;j<m;j++)
                          if(i==j)
                              res[i][j]=1;

                    while(b>0){
                          if(b%2==1)
                               multiply( res, mat,m);
                               b=b/2;
                          multiply(mat,mat,m);
                    }
                long ans=0;
                for(int j=0;j<m;j++)
                   ans=(ans+res[m-1][j])%mod;
                return(ans);
            }
    static long solve(long n,int m){
                     long mat[][] = new long[m][m];// creating recurrence matrix
                      int i1=1,j1=0;
                     for(int i=0;i<m;i++){

                                 if(i1<m)
                                 mat[i1][j1]=1;

                           for(int j=0;j<m;j++)
                            {
                               if(i==0&&j==(m-1))
                                   mat[i][j]=1;
                               if(i==(m-1)&&j==(m-1))
                                   mat[i][j]=1;
                             }
                            i1++;j1++;
                      }
                          return(pow(mat,n-m+1,m));
               }
    public static void main(String args[]) {
               Scanner sc = new Scanner(System.in);
               PrintWriter out = new PrintWriter(System.out);
                 long n = sc.nextLong();
                 int m = sc.nextInt();
                      if(n<m)
                        System.out.println("1");
                      else
                        System.out.println(solve(n,m));
            }
}

import java.util.*;
import java.io.*;
public class s3
{
    static int mod=1000000007;
    static void multiply(long mat1[][], long mat2[][],int m) {
               long res[][] = new long[m][m];

                int i, j, k;

        for (i = 0; i < m; i++)
            for (j = 0; j < m; j++) {
                     res[i][j] = 0;
                for (k = 0; k < m; k++)
                    res[i][j] =(res[i][j]+ mat1[i][k]* mat2[k][j])%mod;
            }
         for(i=0;i<m;i++)
           for( j=0;j<m;j++)
               mat1[i][j]=res[i][j];
    }
    static long pow(long mat[][],long b,int m){

                    long res[][]= new long[m][m];

                    for(int i=0;i<m;i++)
                      for(int j=0;j<m;j++)
                          if(i==j)
                              res[i][j]=1;

                    while(b>0){
                          if(b%2==1)
                               multiply( res, mat,m);
                               b=b/2;
                          multiply(mat,mat,m);
                    }
                long ans=0;
                for(int j=0;j<m;j++)
                   ans=(ans+res[m-1][j])%mod;
                return(ans);
            }
    static long solve(long n,int m){
                     long mat[][] = new long[m][m];
                      int i1=1,j1=0;
                     for(int i=0;i<m;i++){

                                 if(i1<m)
                                 mat[i1][j1]=1;

                           for(int j=0;j<m;j++)
                            {
                               if(i==0&&j==(m-1))
                                   mat[i][j]=1;
                               if(i==(m-1)&&j==(m-1))
                                   mat[i][j]=1;
                             }
                            i1++;j1++;
                      }
                          return(pow(mat,n-m+1,m));
               }
    public static void main(String args[]) {
               Scanner sc = new Scanner(System.in);
               PrintWriter out = new PrintWriter(System.out);
                 long n = sc.nextLong();
                 int m = sc.nextInt();
                      if(n<m)
                        System.out.println("1");
                      else
                        System.out.println(solve(n,m));
            }
}

// Concept : hackerearth matrix exponentiation
import java.util.*;
import java.io.*;
public class s3
{
    static int mod=1000000007;
    static void multiply(long mat1[][], long mat2[][],int m) {
               long res[][] = new long[m][m];

                int i, j, k;

        for (i = 0; i < m; i++)
            for (j = 0; j < m; j++) {
                     res[i][j] = 0;
                for (k = 0; k < m; k++)
                    res[i][j] =(res[i][j]+ mat1[i][k]* mat2[k][j])%mod;
            }
         for(i=0;i<m;i++)
           for( j=0;j<m;j++)
               mat1[i][j]=res[i][j];
    }
    static long pow(long mat[][],long b,int m){

                    long res[][]= new long[m][m];

                    for(int i=0;i<m;i++)
                      for(int j=0;j<m;j++)
                          if(i==j)
                              res[i][j]=1;

                    while(b>0){
                          if(b%2==1)
                               multiply( res, mat,m);
                               b=b/2;
                          multiply(mat,mat,m);
                    }
                long ans=0;
                for(int j=0;j<m;j++)
                   ans=(ans+res[m-1][j])%mod;
                return(ans);
            }
    static long solve(long n,int m){
                     long mat[][] = new long[m][m];
                      int i1=1,j1=0;
                     for(int i=0;i<m;i++){

                                 if(i1<m)
                                 mat[i1][j1]=1;

                           for(int j=0;j<m;j++)
                            {
                               if(i==0&&j==(m-1))
                                   mat[i][j]=1;
                               if(i==(m-1)&&j==(m-1))
                                   mat[i][j]=1;
                             }
                            i1++;j1++;
                      }
                          return(pow(mat,n-m+1,m));
               }
    public static void main(String args[]) {
               Scanner sc = new Scanner(System.in);
               PrintWriter out = new PrintWriter(System.out);
                 long n = sc.nextLong();
                 int m = sc.nextInt();
                      if(n<m)
                        System.out.println("1");
                      else
                        System.out.println(solve(n,m));
            }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author prakharjain
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        DMagicGems solver = new DMagicGems();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems {
        int mod = 1000000007;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            long n = in.nextLong();
            int m = in.nextInt();
            long[] dp = new long[m];

            dp[0] = 1;

            for (int i = 1; i < m; i++) {
                dp[i] += dp[i - 1];
                dp[i] %= mod;

                if (i >= m) {
                    dp[i] += dp[i - m];
                    dp[i] %= mod;
                }

                if (i == m - 1) {
                    dp[i]++;
                    dp[i] %= mod;
                }
            }

            if (n <= m) {
                out.println(dp[(int) n - 1]);
                return;
            }

            MatrixExpo me = new MatrixExpo(m);

            long[][] base = new long[m][m];

            base[0][0] = 1;
            base[0][m - 1] = 1;

            for (int i = 1; i < m; i++) {
                base[i][i - 1] = 1;
            }

            base = me.matrixPower(base, n - m, mod);

            long ans = 0;

            for (int i = 0; i < m; i++) {
                ans += (base[0][i] * dp[m - 1 - i]) % mod;
                ans %= mod;
            }

            out.println(ans);
        }

        class MatrixExpo {
            int n;
            long[][] id;

            public MatrixExpo(int n) {
                this.n = n;
            }

            long[][] matrixPower(long[][] base, long pow, long mod) {
//            if (pow == 0) {
//                return id;
//            }
//            if (pow == 1) {
//                return base;
//            }
//
//            long[][] t = matrixPower(base, pow / 2, mod);
//
//            t = multiplyMatrix(t, t, mod);
//            if (pow % 2 == 1) {
//                t = multiplyMatrix(t, base, mod);
//            }
//
//            return t;

                id = new long[n][n];

                for (int i = 0; i < n; i++)
                    id[i][i] = 1;

                while (pow != 0) {
                    if ((pow & 1) != 0) id = multiplyMatrix(id, base, mod);

                    base = multiplyMatrix(base, base, mod);

                    pow >>= 1;
                }

                return id;
            }

            long[][] multiplyMatrix(long[][] m, long[][] m2, long mod) {
                long[][] ans = new long[n][n];

                for (int i = 0; i < n; i++)
                    for (int j = 0; j < n; j++) {
                        ans[i][j] = 0;
                        for (int k = 0; k < n; k++) {
                            ans[i][j] += (m[i][k] * m2[k][j]) % mod;
                            ans[i][j] %= mod;
                        }
                    }

                return ans;
            }

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void close() {
            writer.close();
        }

        public void println(long i) {
            writer.println(i);
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.util.Map;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.HashMap;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author prakharjain
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        DMagicGems_dac solver = new DMagicGems_dac();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems_dac {
        int max = 10000000;
        long[] dp;
        long n;
        int m;
        int mod = 1000000007;
        Map<Long, Long> map = new HashMap<>();

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            n = in.nextLong();
            m = in.nextInt();

            dp = new long[max];

            dp[0] = 1;

            for (int i = 1; i < max; i++) {
                dp[i] += dp[i - 1];
                dp[i] %= mod;

                if (i >= m) {
                    dp[i] += dp[i - m];
                    dp[i] %= mod;
                }

                if (i == m - 1) {
                    dp[i]++;
                    dp[i] %= mod;
                }
            }

            if (n <= max) {
                out.println(dp[(int) n - 1]);
                return;
            }

            out.print(cal(n));
        }

        long cal(long n) {
            if (n <= max) {
                return dp[(int) n - 1];
            }

            if (map.containsKey(n)) {
                return map.get(n);
            }

            long mid = n / 2;

            long ans = 0;

            long val1 = cal(mid);
            long val2 = cal(n - mid);

            ans += (val1 * val2) % mod;

            for (int i = m - 1; i > 0; i--) {
                val1 = cal(mid - i);
                val2 = cal(n - mid - (m - i));

                ans += (val1 * val2) % mod;
                ans %= mod;
            }

            map.put(n, ans);

            return ans;
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void close() {
            writer.close();
        }

        public void print(long i) {
            writer.print(i);
        }

        public void println(long i) {
            writer.println(i);
        }

    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.util.Map;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.HashMap;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author prakharjain
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        DMagicGems_dac solver = new DMagicGems_dac();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems_dac {
        int max = 200;
        long[] dp;
        long n;
        int m;
        int mod = 1000000007;
        Map<Long, Long> map = new HashMap<>();

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            n = in.nextLong();
            m = in.nextInt();

            dp = new long[max];

            dp[0] = 1;

            for (int i = 1; i < max; i++) {
                dp[i] += dp[i - 1];
                dp[i] %= mod;

                if (i >= m) {
                    dp[i] += dp[i - m];
                    dp[i] %= mod;
                }

                if (i == m - 1) {
                    dp[i]++;
                    dp[i] %= mod;
                }
            }

            if (n <= max) {
                out.println(dp[(int) n - 1]);
                return;
            }

            out.print(cal(n));
        }

        long cal(long n) {
            if (n <= max) {
                return dp[(int) n - 1];
            }

            if (map.containsKey(n)) {
                return map.get(n);
            }

            long mid = n / 2;

            long ans = 0;

            long val1 = cal(mid);
            long val2 = cal(n - mid);

            ans += (val1 * val2) % mod;

            for (int i = m - 1; i > 0; i--) {
                val1 = cal(mid - i);
                val2 = cal(n - mid - (m - i));

                ans += (val1 * val2) % mod;
                ans %= mod;
            }

            map.put(n, ans);

            return ans;
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void close() {
            writer.close();
        }

        public void print(long i) {
            writer.print(i);
        }

        public void println(long i) {
            writer.println(i);
        }

    }
}

import java.io.*;
import java.util.*;

public class CFD {

    BufferedReader br;
    PrintWriter out;
    StringTokenizer st;
    boolean eof;
    private static long MOD = 1000L * 1000L * 1000L + 7;
    private static final int[] dx = {0, -1, 0, 1};
    private static final int[] dy = {1, 0, -1, 0};
    private static final String yes = "Yes";
    private static final String no = "No";

    long n;
    int m;
    void solve() throws IOException {
        n = nextLong();
        m = nextInt();
        long[][] mat = new long[m][m];
        mat[0][0] = 1;
        mat[0][m - 1] = 1;
        for (int i = 1; i < m; i++) {
            mat[i][i - 1] = 1;
        }

        long[][] powN = matrixPow(mat, n);
        long res = powN[0][0];
        outln(res % MOD);
    }

    long[][] matrixPow(long[][] a, long p) {
        if (p == 0) {
            long[][] res = new long[m][m];
            for (int i = 0; i < m; i++) {
                res[i][i] = 1;
            }
            return res;
        } else if (p % 2 == 0) {
            return matrixPow(matrixMul(a, a), p / 2);
        } else {
            return matrixMul(a, matrixPow(a, p - 1));
        }
    }

    long[][] matrixMul(long[][] a, long[][] b) {
        int n = a.length;
        int m = a[0].length;
        int k = b[0].length;
        long[][] res = new long[n][k];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < k; j++) {
                for (int p = 0; p < m; p++) {
                    long extra = a[i][p] * b[p][j] % MOD;
                    res[i][j] += extra;
                    if (res[i][j] >= MOD) {
                        res[i][j] -= MOD;
                    }
                }
            }
        }
        return res;
    }

    void shuffle(int[] a) {
        int n = a.length;
        for(int i = 0; i < n; i++) {
            int r = i + (int) (Math.random() * (n - i));
            int tmp = a[i];
            a[i] = a[r];
            a[r] = tmp;
        }
    }
    long gcd(long a, long b) {
        while(a != 0 && b != 0) {
            long c = b;
            b = a % b;
            a = c;
        }
        return a + b;
    }
    private void outln(Object o) {
        out.println(o);
    }
    private void out(Object o) {
        out.print(o);
    }
    private void formatPrint(double val) {
        outln(String.format("%.9f%n", val));
    }
    public CFD() throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
        solve();
        out.close();
    }
    public static void main(String[] args) throws IOException {
        new CFD();
    }

    public long[] nextLongArr(int n) throws IOException{
        long[] res = new long[n];
        for(int i = 0; i < n; i++)
            res[i] = nextLong();
        return res;
    }
    public int[] nextIntArr(int n) throws IOException {
        int[] res = new int[n];
        for(int i = 0; i < n; i++)
            res[i] = nextInt();
        return res;
    }
    public String nextToken() {
        while (st == null || !st.hasMoreTokens()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (Exception e) {
                eof = true;
                return null;
            }
        }
        return st.nextToken();
    }
    public String nextString() {
        try {
            return br.readLine();
        } catch (IOException e) {
            eof = true;
            return null;
        }
    }
    public int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }
    public long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }
    public double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
}

import java.util.*;
import java.io.*;
import java.text.*;
//Solution Credits: Taranpreet Singh
public class Main{
    //SOLUTION BEGIN
    void pre() throws Exception{}
    void solve(int TC) throws Exception{
        long n = nl();int m = ni();
        long[][] mat = new long[m][m];
        for(int i = 1; i< m; i++)mat[i][i-1] = 1;
        mat[0][0] = 1;mat[0][m-1] = 1;
        mat = pow(mat, n);
        pn(mat[0][0]);
    }
    long[][] pow(long[][] m, long p) throws Exception{
        long[][] o = new long[m.length][m.length], t = new long[m.length][m.length];
        for(int i = 0; i< m.length; i++)for(int j = 0; j< m.length; j++)t[i][j] = m[i][j];
        for(int i = 0; i< m.length; i++)o[i][i] = 1;
        while(p>0){
            if((p&1)==1)o = multiply(o,t);
            t = multiply(t,t);
            p>>=1;
        }
        return o;
    }
    long[][] multiply(long[][] a, long[][] b) throws Exception{
        if(a[0].length!=b.length)throw new Exception();
        long[][] c = new long[a.length][b[0].length];
        for(int i = 0; i< a.length; i++)
            for(int j = 0; j< b[0].length; j++){
                c[i][j] = 0;
                for(int k = 0; k< b.length; k++){
                    c[i][j] += (a[i][k]*b[k][j])%mod;
                    if(c[i][j]>=mod)c[i][j] -= mod;
                }
            }
        return c;
    }
    //SOLUTION END
    void hold(boolean b)throws Exception{if(!b)throw new Exception("Hold right there, Sparky!");}
    long mod = (long)1e9+7, IINF = (long)1e18;
    final int INF = (int)1e9, MX = (int)3e5+1;
    DecimalFormat df = new DecimalFormat("0.00000000000");
    double PI = 3.1415926535897932384626433832792884197169399375105820974944, eps = 1e-8;
    static boolean multipleTC = false, memory = false;
    FastReader in;PrintWriter out;
    void run() throws Exception{
        in = new FastReader();
        out = new PrintWriter(System.out);
        int T = (multipleTC)?ni():1;
        //Solution Credits: Taranpreet Singh
        pre();for(int t = 1; t<= T; t++)solve(t);
        out.flush();
        out.close();
    }
    public static void main(String[] args) throws Exception{
        if(memory)new Thread(null, new Runnable() {public void run(){try{new Main().run();}catch(Exception e){e.printStackTrace();}}}, "1", 1 << 28).start();
        else new Main().run();
    }
    long gcd(long a, long b){return (b==0)?a:gcd(b,a%b);}
    int gcd(int a, int b){return (b==0)?a:gcd(b,a%b);}
    int bit(long n){return (n==0)?0:(1+bit(n&(n-1)));}
    void p(Object o){out.print(o);}
    void pn(Object o){out.println(o);}
    void pni(Object o){out.println(o);out.flush();}
    String n()throws Exception{return in.next();}
    String nln()throws Exception{return in.nextLine();}
    int ni()throws Exception{return Integer.parseInt(in.next());}
    long nl()throws Exception{return Long.parseLong(in.next());}
    double nd()throws Exception{return Double.parseDouble(in.next());}

    class FastReader{
        BufferedReader br;
        StringTokenizer st;
        public FastReader(){
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        public FastReader(String s) throws Exception{
            br = new BufferedReader(new FileReader(s));
        }

        String next() throws Exception{
            while (st == null || !st.hasMoreElements()){
                try{
                    st = new StringTokenizer(br.readLine());
                }catch (IOException  e){
                    throw new Exception(e.toString());
                }
            }
            return st.nextToken();
        }

        String nextLine() throws Exception{
            String str = "";
            try{
                str = br.readLine();
            }catch (IOException e){
                throw new Exception(e.toString());
            }
            return str;
        }
    }
}

//package math_codet;

import java.io.*;
import java.util.*;

public class lets_do {
    FastReader in;
    PrintWriter out;
    Helper_class h;
    final long mod = 1000000007;
    final int MAXN = 100005;
    final int lgN = 20;
    final int INF = (int)1e12;
    public static void main(String[] args) throws java.lang.Exception{
        new lets_do().run();
    }
    void run() throws Exception{
        in=new FastReader(System.in);
        out = new PrintWriter(System.out);
        h = new Helper_class();
        int t = 1;
        while(t-->0)
            solve();
        out.flush();
        out.close();
    }
    long[][] mult(long[][] hola1, long[][] hola2, int m){
        int i = 0, j = 0, k = 0;
        long[][] temp = new long[m][m];
        for (i = 0; i < m; i++){
            for (j = 0; j < m; j++){
                for (k = 0; k < m; k++)
                    temp[i][j] = (temp[i][j] + hola1[i][k] * hola2[k][j]) % mod;
            }
        }
        return temp;
    }
    void solve(){
        long n = h.nl();
        int m = h.ni();
        long[][] mat = new long[m][m];
        int i = 0, j = 0;
        for(i = 1; i < m; i++)
            mat[i][i - 1] = 1;
        mat[0][0] = 1;
        mat[0][m - 1] = 1;
        long[][] res = new long[m][m];
        for(i = 0; i < m; i++)
            res[i][i] = 1;
        while(n  > 0){
            if((n & 1) == 1)
                res = mult(res, mat, m);
            mat = mult(mat, mat, m);
            n >>= 1;
        }
        long sum = 0;
        for(i = 0; i < m; i++){
            sum += res[m - 1][i];
            sum %= mod;
        }
        h.pn(sum);
    }

    static final Comparator<Pair> com=new Comparator<Pair>(){
        public int compare(Pair a, Pair b){
            if(Integer.compare(a.y, b.y) != 0)
                return Integer.compare(a.y, b.y);
            else
                return Integer.compare(a.x, b.x);
        }
    };
    class Pair{
        int x;
        int y;
        Pair(int p, int q){
            y = p;
            x = q;
        }
    }
    class Edge{
        int u , v; long wt;
        Edge(int a, int b, long w){
            u = a;
            v = b;
            wt = w;
        }
        int other(int x) {
            return u ^ v ^ x;
        }
    }
    class Helper_class{
        long gcd(long a, long b){return (b==0)?a:gcd(b,a%b);}
        int gcd(int a, int b){return (b==0)?a:gcd(b,a%b);}
        int bitcount(long n){return (n==0)?0:(1+bitcount(n&(n-1)));}
        void p(Object o){out.print(o);}
        void pn(Object o){out.println(o);}
        void pni(Object o){out.println(o);out.flush();}
        String n(){return in.next();}
        String nln(){return in.nextLine();}
        int ni(){return Integer.parseInt(in.next());}
        long nl(){return Long.parseLong(in.next());}
        double nd(){return Double.parseDouble(in.next());}

        long mul(long a,long b){
            if(a>=mod)a%=mod;
            if(b>=mod)b%=mod;
            a*=b;
            if(a>=mod)a%=mod;
            return a;
        }
        long modPow(long a, long p){
            long o = 1;
            while(p>0){
                if((p&1)==1)o = mul(o,a);
                a = mul(a,a);
                p>>=1;
            }
            return o;
        }
        long add(long a, long b){
            if(a>=mod)a%=mod;
            if(b>=mod)b%=mod;
            if(b<0)b+=mod;
            a+=b;
            if(a>=mod)a-=mod;
            return a;
        }
    }

    class FastReader{
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;

        public FastReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1)
                throw new UnknownError();
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new UnknownError();
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public int peek() {
            if (numChars == -1)
                return -1;
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    return -1;
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar];
        }

        public void skip(int x) {
            while (x-- > 0)
                read();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public String nextString() {
            return next();
        }

        public String next() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuffer res = new StringBuffer();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isSpaceChar(c));

            return res.toString();
        }

        public String nextLine() {
            StringBuffer buf = new StringBuffer();
            int c = read();
            while (c != '\n' && c != -1) {
                if (c != '\r')
                    buf.appendCodePoint(c);
                c = read();
            }
            return buf.toString();
        }

        public double nextDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, nextInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, nextInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }

        public boolean hasNext() {
            int value;
            while (isSpaceChar(value = peek()) && value != -1)
                read();
            return value != -1;
        }

        private boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }
    }
}

//package math_codet;

import java.io.*;
import java.util.*;

public class lets_do {
    FastReader in;
    PrintWriter out;
    Helper_class h;
    final long mod = 1000000007;
    final int MAXN = 100005;
    final int lgN = 20;
    final int INF = (int)1e12;
    public static void main(String[] args) throws java.lang.Exception{
        new lets_do().run();
    }
    void run() throws Exception{
        in=new FastReader(System.in);
        out = new PrintWriter(System.out);
        h = new Helper_class();
        int t = 1;
        while(t-->0)
            solve();
        out.flush();
        out.close();
    }
    long[][] mult(long[][] hola1, long[][] hola2, int m){
        int i = 0, j = 0, k = 0;
        long[][] temp = new long[m][m];
        for (i = 0; i < m; i++){
            for (j = 0; j < m; j++){
                for (k = 0; k < m; k++)
                    temp[i][j] = (temp[i][j] + hola1[i][k] * hola2[k][j]) % mod;
            }
        }
        return temp;
    }
    void solve(){
        long n = h.nl();
        int m = h.ni();
        long[][] mat = new long[m][m];
        int i = 0, j = 0;
        for(i = 1; i < m; i++)
            mat[i][i - 1] = 1;
        mat[0][0] = 1;
        mat[0][m - 1] = 1;
        long[][] res = new long[m][m];
        for(i = 0; i < m; i++)
            res[i][i] = 1;
        n -= m - 1;
        while(n  > 0){
            if((n & 1) == 1)
                res = mult(res, mat, m);
            mat = mult(mat, mat, m);
            n >>= 1;
        }
        long sum = 0;
        for(i = 0; i < m; i++){
            sum += res[0][i];
            sum %= mod;
        }
        h.pn(sum);
    }

    static final Comparator<Pair> com=new Comparator<Pair>(){
        public int compare(Pair a, Pair b){
            if(Integer.compare(a.y, b.y) != 0)
                return Integer.compare(a.y, b.y);
            else
                return Integer.compare(a.x, b.x);
        }
    };
    class Pair{
        int x;
        int y;
        Pair(int p, int q){
            y = p;
            x = q;
        }
    }
    class Edge{
        int u , v; long wt;
        Edge(int a, int b, long w){
            u = a;
            v = b;
            wt = w;
        }
        int other(int x) {
            return u ^ v ^ x;
        }
    }
    class Helper_class{
        long gcd(long a, long b){return (b==0)?a:gcd(b,a%b);}
        int gcd(int a, int b){return (b==0)?a:gcd(b,a%b);}
        int bitcount(long n){return (n==0)?0:(1+bitcount(n&(n-1)));}
        void p(Object o){out.print(o);}
        void pn(Object o){out.println(o);}
        void pni(Object o){out.println(o);out.flush();}
        String n(){return in.next();}
        String nln(){return in.nextLine();}
        int ni(){return Integer.parseInt(in.next());}
        long nl(){return Long.parseLong(in.next());}
        double nd(){return Double.parseDouble(in.next());}

        long mul(long a,long b){
            if(a>=mod)a%=mod;
            if(b>=mod)b%=mod;
            a*=b;
            if(a>=mod)a%=mod;
            return a;
        }
        long modPow(long a, long p){
            long o = 1;
            while(p>0){
                if((p&1)==1)o = mul(o,a);
                a = mul(a,a);
                p>>=1;
            }
            return o;
        }
        long add(long a, long b){
            if(a>=mod)a%=mod;
            if(b>=mod)b%=mod;
            if(b<0)b+=mod;
            a+=b;
            if(a>=mod)a-=mod;
            return a;
        }
    }

    class FastReader{
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;

        public FastReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1)
                throw new UnknownError();
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new UnknownError();
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public int peek() {
            if (numChars == -1)
                return -1;
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    return -1;
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar];
        }

        public void skip(int x) {
            while (x-- > 0)
                read();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public String nextString() {
            return next();
        }

        public String next() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuffer res = new StringBuffer();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isSpaceChar(c));

            return res.toString();
        }

        public String nextLine() {
            StringBuffer buf = new StringBuffer();
            int c = read();
            while (c != '\n' && c != -1) {
                if (c != '\r')
                    buf.appendCodePoint(c);
                c = read();
            }
            return buf.toString();
        }

        public double nextDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, nextInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, nextInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }

        public boolean hasNext() {
            int value;
            while (isSpaceChar(value = peek()) && value != -1)
                read();
            return value != -1;
        }

        private boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }
    }
}

import java.io.*;
import java.util.*;

public class D_MagicGems {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader inp = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Solver solver = new Solver();
        solver.solve(inp, out);
        out.close();
    }

    private static class Solver {
        private void solve(InputReader inp, PrintWriter out) {
            long n = inp.nextLong();
            int m = inp.nextInt();
            long[] f = new long[m];
            Arrays.fill(f, 1);
            long[][] t = new long[m][m];
            // identity matrix for previous values
            for (int i = 0; i < m - 1; i++) t[i][i+1] = 1;
            t[m-1][0] = 1;      // dp(i - m)
            t[m-1][m-1] = 1;    // dp (i - 1)
            // T^n * f. Index 0 contains value for dp[n]
            out.println(pow(t, f, n)[0]);
        }

        private static final int MOD = 1000000007;
        private static final long BIG = 8L * (long) MOD * MOD;

        /*
        Matrix A, exponent e, vector v
        (A^e)*v
        */
        public static long[] pow(long[][] A, long[] v, long e) {
            for(int i = 0;i < v.length;i++) {
                if(v[i] >= MOD) v[i] %= MOD;
            }
            long[][] MUL = A;
            for(;e > 0;e>>>=1) {
                if((e&1)==1)v = mul(MUL, v);
                MUL = p2(MUL);
            }
            return v;
        }

        /*
        Matrix A, vector v
        A*v
         */
        public static long[] mul(long[][] A, long[] v) {
            int m = A.length;
            int n = v.length;
            long[] w = new long[m];
            for(int i = 0;i < m;i++){
                long sum = 0;
                for(int k = 0;k < n;k++){
                    sum += A[i][k] * v[k];
                    if(sum >= BIG) sum -= BIG;
                }
                w[i] = (sum % MOD);
            }
            return w;
        }

        /*
        Square matrix A (be careful about negative values)
         */
        public static long[][] p2(long[][] A) {
            int n = A.length;
            long[][] C = new long[n][n];
            for(int i = 0;i < n;i++){
                long[] sum = new long[n];
                for(int k = 0;k < n;k++){
                    for(int j = 0;j < n;j++){
                        sum[j] += A[i][k] * A[k][j];
                        if(sum[j] >= BIG) sum[j] -= BIG;
                    }
                }
                for(int j = 0;j < n;j++){
                    C[i][j] = (sum[j] % MOD);
                }
            }
            return C;
        }
    }

    static class InputReader {
        BufferedReader reader;
        StringTokenizer tokenizer;

        InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
            return Long.parseLong(next());
        }
    }
}

import java.io.*;
import java.util.*;

public class D {
    class Writer {
        PrintWriter cout;

        Writer() throws IOException {
            cout = new PrintWriter(System.out);
        }

        Writer(String name) throws IOException {
            cout = new PrintWriter(new FileWriter(name));
        }

        StringBuilder out = new StringBuilder();

        void print(Object a) {
            out.append(a);
        }

        void close() {
            cout.print(out.toString());
            cout.close();
        }
    }

    class Reader {
        BufferedReader in;

        Reader() throws IOException {
            in = new BufferedReader(new InputStreamReader(System.in), 32768);
        }

        Reader(String name) throws IOException {
            in = new BufferedReader(new FileReader(name));
        }

        StringTokenizer tokin = new StringTokenizer("");

        String next() throws IOException {
            if (!tokin.hasMoreTokens()) {
                tokin = new StringTokenizer(in.readLine());
            }
            return tokin.nextToken();
        }

        int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        long nextLong() throws IOException {
            return Long.parseLong(next());
        }
    }

    long mod = (long) (1e9 + 7);
    int m;

    HashMap<Long, Long> h;

    long calck(long n) {
        if (n < 0) {
            return 0;
        } else {
            long ans = 0;
            if (h.containsKey(n)) {
                ans = h.get(n);
            } else {
                long n1 = n / 2;
                long n2 = n - n1;
                ans = (ans + calck(n1) * calck(n2)) % mod;
                for (int i = 1; i < m; i++) {
                    ans = (ans + (calck(n1 - i) * calck(n2 - (m - i))) % mod) % mod;
                    //ans += calck(n1 - i) * calck(n2 - (m - i));
                }
                h.put(n, ans);
            }
            return ans;
        }
    }

    void solve() throws IOException {
        Reader in = new Reader();
        Writer out = new Writer();
        long n = in.nextLong();
        m = in.nextInt();
        h = new HashMap<>();
        for (int i = 0; i < m; i++) {
            h.put((long) i, (long) 1);
        }
        out.print(calck(n));
        out.close();
    }

    public static void main(String[] args) throws IOException {
        new D().solve();
    }
}

import java.util.*;
import java.io.*;
import java.math.BigInteger;

public class Main
{
    static final long mod=(int)1e9+7;
    static long[][] mat,mul;
    public static void main(String[] args) throws Exception
    {
    	FastReader in=new FastReader();
    	PrintWriter pw=new PrintWriter(System.out);
	    long n=in.nextLong();
	    int m=in.nextInt();
	    if(n<m)
	    {
	    	System.out.println(1);
	    	return;
	    }
	    mat=new long[m][m];
	    mul=new long[m][m];
	    mul[0][0]=mul[0][m-1]=mat[0][0]=1;
	    for(int i=1;i<m;i++)
	    	mul[i][i-1]=mat[i][i]=1;
	    matExpo(n-m);
	    long ans=2*mat[0][0];
	    ans%=mod;
	    for(int i=1;i<m;i++)
		    ans=(ans+mat[0][i])%mod;
	    pw.print(ans);
    	pw.flush();
    }

    public static void matExpo(long n)
    {
    	while(n>0)
    	{
    		if((n&1)==1)
    			matMul(mat,mul);
    		matMul(mul,mul);
    		n>>=1;
    	}
    }

    public static void matMul(long[][] mat,long[][] mul)
    {
    	long[][] m1=new long[mat.length][mat.length];
    	for(int i=0;i<mat.length;i++)
    	{
    		for(int j=0;j<mat.length;j++)
    		{
    			long c=0;
    			for(int k=0;k<mat.length;k++)
    			{
    				c+=mat[i][k]*mul[k][j];
    				c%=mod;
    			}
    			m1[i][j]=c;
    		}
    	}
    	for(int i=0;i<mat.length;i++)
    		for(int j=0;j<mat.length;j++)
    			mat[i][j]=m1[i][j];
    }
}

class FastReader
{
    BufferedReader br;
    StringTokenizer st;

    public FastReader()
    {
        br=new BufferedReader(new InputStreamReader(System.in));
    }

    public String next() throws IOException
    {
        if(st==null || !st.hasMoreElements())
        {
            st=new StringTokenizer(br.readLine());
        }
        return st.nextToken();
    }

    public int nextInt() throws IOException
    {
        return Integer.parseInt(next());
    }

    public long nextLong() throws IOException
    {
        return Long.parseLong(next());
    }
}

import java.util.*;

public class heck
{
    static long mod = (long)1e9+7;
    static long[][] I;

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        long n = in.nextLong();
        int m = in.nextInt();

        I = new long[m][m];
        long[][] M = new long[m][m];
        for (int i = 1; i < m; i++)
            I[i][i] = M[i-1][i] = 1L;
        I[0][0] = M[0][0] = M[m-1][0] = 1L;

        M = exp(M, n);
        System.out.println(M[0][0]);
        in.close();
    }

    public static long[][] exp(long[][] M, long n)
    {
        if (n == 0) return I;
        if (n == 1) return M;
        long[][] res = exp(M, n/2);
        res = mult(res, res);
        if (n %2 == 0) return res;
        return mult(res, M);
    }

    public static long[][] mult(long[][] p, long[][] q)
    {
        long[][] r = new long[p.length][q[0].length];
        for (int i = 0; i < p.length; i++)
            for (int j = 0; j < q[0].length; j++)
                for (int k = 0; k < q.length; k++)
                {
                    r[i][j] += p[i][k]*q[k][j];
                    r[i][j] %= mod;
                }
        return r;
    }
}

import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.nio.charset.StandardCharsets.UTF_8;

public class Main {

    private static final long p = 1000000007;

    public static void main(String[] args) throws IOException {
        try (BufferedReader in = new BufferedReader(new InputStreamReader(System.in, UTF_8));
             BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out, UTF_8))) {
            StringTokenizer tokens = new StringTokenizer(in.readLine());
            long n = parseLong(tokens.nextToken());
            int m = parseInt(tokens.nextToken());
            if (n < m) {
                out.write("1");
                out.newLine();
            } else {
                long[] vec = new long[m];
                Arrays.fill(vec, 1);
                long[][] matrix = new long[m][m];
                fillMatrix(matrix);
                long deg = n - m + 1;
                matrix = deg(matrix, deg);
                vec = multiply(matrix, vec);
                out.write(vec[0] + "");
                out.newLine();
            }
        }
    }

    private static void fillMatrix(long[][] a) {
        a[0][0] = 1;
        a[0][a[0].length - 1] = 1;
        for (int i = 1; i < a.length; i++) {
            a[i][i - 1] = 1;
        }
    }

    private static long[] multiply(long[][] m, long[] vec) {
        long[] c = new long[vec.length];
        for (int i = 0; i < c.length; i++) {
            for (int j = 0; j < m[i].length; j++) {
                c[i] += m[i][j] * vec[j];
                c[i] %= p;
            }
        }
        return c;
    }

    private static long[][] deg(long[][] a, long n) {
        if (n == 1) {
            return a;
        }
        long[][] sqr = multiply(a, a);
        if (n % 2 == 0) {
            return deg(sqr, n / 2);
        } else {
            return multiply(deg(sqr, n / 2), a);
        }
    }

    private static long[][] multiply(long[][] a, long[][] b) {
        long[][] c = new long[a.length][b[0].length];
        for (int i = 0; i < c.length; i++) {
            for (int j = 0; j < c[i].length; j++) {
                c[i][j] = 0;
                for (int k = 0; k < a[0].length; k++) {
                    c[i][j] += a[i][k] * b[k][j];
                    c[i][j] %= p;
                }
            }
        }
        return c;
    }
}

import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        FastReader in = new FastReader();
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        new Main().solve(in, out);
        out.close();
    }

    final static long MOD = (long) 1e9+7;

    void solve(FastReader in, PrintWriter out) {
        long n = in.nextLong();
        int m = in.nextInt();
        long[][] vec = init(m, 1, 1);
        long[][] mat = init(m, m, 0);
        mat[0][0] = mat[0][m-1] = 1;
        for (int i = 1; i < m; ++i) {
            mat[i][i-1] = 1;
        }
        long[][] expMat = modPow(mat, Math.max(0, n-m+1));
        long[][] ans = modMul(expMat, vec);
        out.println(ans[0][0]);
    }

    long[][] init(int r, int c, int v) {
        long[][] ans = new long[r][c];
        if (v != 0) {
            for (int i = 0; i < r; ++i) {
                for (int j = 0; j < c; ++j) {
                    ans[i][j] = v;
                }
            }
        }
        return ans;
    }

    long[][] modMul(long[][] m1, long[][] m2) {
        int r = m1.length, c = m2[0].length;
        long[][] ans = init(r, c, 0);
        for (int i = 0; i < r; ++i) {
            for (int k = 0; k < m2.length; ++k) {
                for (int j = 0; j < c; ++j) {
                    ans[i][j] = (ans[i][j]+m1[i][k]*m2[k][j])%MOD;
                }
            }
        }
        return ans;
    }

    long[][] modPow(long[][] mat, long b) {
        int n = mat.length;
        long[][] ans = init(n, n, 0);
        for (int i = 0; i < n; ++i) {
            ans[i][i] = 1;
        }
        while (b > 0) {
            if ((b&1) > 0) {
                ans = modMul(ans, mat);
            }
            mat = modMul(mat, mat);
            b >>= 1;
        }
        return ans;
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException  e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        FastReader in = new FastReader();
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        new Main().solve(in, out);
        out.close();
    }

    final static long MOD = (long) 1e9+7;

    void solve(FastReader in, PrintWriter out) {
        long n = in.nextLong();
        int m = in.nextInt();
        long[][] vec = init(m, 1, 1);
        long[][] mat = init(m, m, 0);
        mat[0][0] = mat[0][m-1] = 1;
        for (int i = 1; i < m; ++i) {
            mat[i][i-1] = 1;
        }
        long[][] expMat = modPow(mat, Math.max(0, n-m+1));
        long[][] ans = modMul(expMat, vec);
        out.println(ans[0][0]);
    }

    long[][] init(int r, int c, int v) {
        long[][] ans = new long[r][c];
        if (v != 0) {
            for (int i = 0; i < r; ++i) {
                for (int j = 0; j < c; ++j) {
                    ans[i][j] = v;
                }
            }
        }
        return ans;
    }

    long[][] modMul(long[][] m1, long[][] m2) {
        int r = m1.length, c = m2[0].length;
        long[][] ans = init(r, c, 0);
        for (int i = 0; i < r; ++i) {
            for (int j = 0; j < c; ++j) {
                for (int k = 0; k < m2.length; ++k) {
                    ans[i][j] = (ans[i][j]+m1[i][k]*m2[k][j])%MOD;
                }
            }
        }
        return ans;
    }

    long[][] modPow(long[][] mat, long b) {
        int n = mat.length;
        long[][] ans = init(n, n, 0);
        for (int i = 0; i < n; ++i) {
            ans[i][i] = 1;
        }
        while (b > 0) {
            if ((b&1) > 0) {
                ans = modMul(ans, mat);
            }
            mat = modMul(mat, mat);
            b >>= 1;
        }
        return ans;
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException  e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.util.*;
import java.io.*;
import java.math.*;
public class Main
{
    static class Reader
    {
        private InputStream mIs;private byte[] buf = new byte[1024];private int curChar,numChars;public Reader() { this(System.in); }public Reader(InputStream is) { mIs = is;}
        public int read() {if (numChars == -1) throw new InputMismatchException();if (curChar >= numChars) {curChar = 0;try { numChars = mIs.read(buf);} catch (IOException e) { throw new InputMismatchException();}if (numChars <= 0) return -1; }return buf[curChar++];}
        public String nextLine(){int c = read();while (isSpaceChar(c)) c = read();StringBuilder res = new StringBuilder();do {res.appendCodePoint(c);c = read();}while (!isEndOfLine(c));return res.toString() ;}
        public String s(){int c = read();while (isSpaceChar(c)) c = read();StringBuilder res = new StringBuilder();do {res.appendCodePoint(c);c = read();}while (!isSpaceChar(c));return res.toString();}
        public long l(){int c = read();while (isSpaceChar(c)) c = read();int sgn = 1;if (c == '-') { sgn = -1 ; c = read() ; }long res = 0; do{ if (c < '0' || c > '9') throw new InputMismatchException();res *= 10 ; res += c - '0' ; c = read();}while(!isSpaceChar(c));return res * sgn;}
        public int i(){int c = read() ;while (isSpaceChar(c)) c = read();int sgn = 1;if (c == '-') { sgn = -1 ; c = read() ; }int res = 0;do{if (c < '0' || c > '9') throw new InputMismatchException();res *= 10 ; res += c - '0' ; c = read() ;}while(!isSpaceChar(c));return res * sgn;}
        public double d() throws IOException {return Double.parseDouble(s()) ;}
        public boolean isSpaceChar(int c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1; }
        public boolean isEndOfLine(int c) { return c == '\n' || c == '\r' || c == -1; }
        public int[] arr(int n){int[] ret = new int[n];for (int i = 0; i < n; i++) {ret[i] = i();}return ret;}
    }

           //       |----|       /\      |    |   -----   |
           //       |   /       /  \     |    |     |     |
           //       |--/       /----\    |----|     |     |
           //       |   \     /      \   |    |     |     |
           //       |    \   /        \  |    |   -----   -------

    static int p,q,n;
    static long map[][];
    static long mod=1000000007;
    static int size;
    public static long[][] expo(long pow)
    {
        long ans[][]=new long[size][size];
        for(int i=0;i<size;i++)
        ans[i][i]=1;
        while(pow!=0)
        {
            if((pow&1)!=0)
                ans=multiplyMatrix(ans, map);
            map=multiplyMatrix(map, map);
            pow/=2;
        }
        return ans;
    }
    public static long[][] multiplyMatrix(long m[][], long m2[][])
    {
        long ans[][]=new long[size][size];
        for(int i=0;i<size;i++)
        for(int j=0;j<size;j++)
        {
            ans[i][j] = 0;
            for(int k=0;k<size;k++)
            {
                ans[i][j]+=(m[i][k]*m2[k][j]);
                if(ans[i][j]>=mod)
                ans[i][j]%=mod;
            }
        }
        return  ans;
    }
    public static void main(String[] args)throws IOException
    {
        PrintWriter out= new PrintWriter(System.out);
        Reader sc=new Reader();
        long n=sc.l();
        int m=sc.i();
        size=m;
        if(n<m)
        out.println(1);
        else
        {
            map=new long[size][size];
            for(int i=0;i<m;i++)
            {
                if(i==0)
                {
                    map[i][0]=1;
                    map[i][m-1]=1;
                }
                else
                map[i][i-1]=1;
            }
            long ans[][]=expo(n-m+1);
            long sum=0;
            for(int i=0;i<m;i++)
            sum+=ans[0][i];
            out.println(sum%mod);
        }
        out.flush();
    }
}

import java.io.*;
import java.util.*;

public class Main {
	static long mod=1000000007;
	public static void main(String[] args){
		long n=nl();
		int m=ni();

		if(n<m){
			pl(1);
			flush();
			return;
		}
		long[][] mat=new long[m][m];
		for(int i=0;i<m;i++){
			if(i==0){
				mat[0][0]=1;
				mat[0][m-1]=1;
			}else{
				mat[i][i-1]=1;
			}
		}
		long sisu=n-m+1;
		mat=pow(mat,sisu,mod);
		long res=0;
		for(int i=0;i<m;i++) res=(res+mat[0][i])%mod;

		pl(res);
		flush();
	}
	static long[][] mul(long[][] a,long[][] b,long mod){
		long[][] res=new long[a.length][b[0].length];
		for(int i=0;i<a.length;i++){
			for(int j=0;j<b[0].length;j++){
				for(int k=0;k<a[i].length;k++){
					res[i][j]+=a[i][k]*b[k][j]%mod;
					res[i][j]%=mod;
				}
			}
		}
		return res;
	}
	static long[][] pow(long[][] a,long b,long mod){
		long[][]res=new long[a.length][a.length];
		for(int i=0;i<a.length;i++) res[i][i]=1;
		while(b>0){
			if(b%2==1) res=mul(res,a,mod);
			a=mul(a,a,mod);
			b/=2;
		}
		return res;
	}

	private static final byte[] buffer = new byte[1024];
	private static int ptr = 0;
	private static int buflen = 0;
	private static boolean hasNextByte() {
		if (ptr < buflen)  return true;
		else{
			ptr = 0;
			try {
				buflen = System.in.read(buffer);
			} catch (IOException e) {e.printStackTrace();}
			if (buflen <= 0)  return false;
		}
		return true;
	}
	private static int readByte() { return hasNextByte() ? buffer[ptr++] : -1;}
	private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
	private static void skipUnprintable() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++;}
	public static boolean hasNext() { skipUnprintable(); return hasNextByte();}
	public static String next() {
		if (!hasNext()) throw new NoSuchElementException();
		StringBuilder sb = new StringBuilder();
		for(int b = readByte();isPrintableChar(b);b = readByte()) {
			sb.appendCodePoint(b);
		}
		return sb.toString();
	}
	public static int nextInt() {return (int)nextLong();}
	public static long nextLong() {
		if (!hasNext()) throw new NoSuchElementException();
		long n = 0;
		boolean minus = false;
		int b = readByte();
		if (b == '-') {
			minus = true;
			b = readByte();
		}
		if (b < '0' || '9' < b)  throw new NumberFormatException();
		while(true){
			if ('0' <= b && b <= '9') n = n * 10 + b-'0';
			else if(b == -1 || !isPrintableChar(b)) return minus ? -n : n;
			else throw new NumberFormatException();
			b = readByte();
		}
	}
	public static long[] nextLongArray(int i){
		long[] result=new long[i];
		for(int j=0;j<i;j++)  result[j]=nextLong();
		return result;
	}
	public static void nextLongArray(long[]... arrays){
		for(int j=0;j<arrays[0].length;j++)
			for(long[] array:arrays) array[j]=nextLong();
	}
	public static int[] nextIntArray(int i){
		int[] result=new int[i];
		for(int j=0;j<i;j++)  result[j]=nextInt();
		return result;
	}
	public static void nextIntArray(int[]... arrays){
		for(int j=0;j<arrays[0].length;j++)
			for(int[] array:arrays)  array[j]=nextInt();
	}
	public static int ni(){return nextInt();}
	public static long nl(){return nextLong();}
	public static int[] nia(int n){return nextIntArray(n);}
	public static long[] nla(int n){return nextLongArray(n);}
	public static String ne(){return next();}

	static StringBuilder sb=new StringBuilder();
	public static void flush(){
		System.out.print(sb);
		sb=new StringBuilder();
	}
	public static void pr(Object o){sb.append(o);}
	public static void pl(Object o){sb.append(o).append("\n");}
	public static void pl(){sb.append("\n");}
	public static int lastLowerIndex(long[] array,long lo){return lastLowerOrEqualIndex(array,lo-1);}
	public static int lastLowerOrEqualIndex(long[] array,long lo){
		int res=Arrays.binarySearch(array,lo);
		return res<0?-res-2:res;
	}
	public static long gcd(long a,long b){
		if(a>b)a%=b;
		while(a>0){
			b%=a;
			if(b==0)return a;
			a%=b;
		}
		return b;
	}
	public static long modPow(long a,long b,long mod){
		long c=1;
		while(b>0){
			if(b%2==1)  c=(c*a)%mod;
			a=(a*a)%mod;
			b/=2;
		}
		return c;
	}
	public static long inv(long a,long mod){
		long b=mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d=a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		return p < 0 ? p + mod : p;
	}
	static long time=0;
	public static void time(){
		if(time==0) time=System.nanoTime();
		else{
			long t=System.nanoTime();
			pl((t-time)/1000000000.0+"sec");
			time=t;
		}
	}
	public static Integer[] sortedIndex(long[] a){
            Integer[] res=new Integer[a.length];
            for(int i=0;i<a.length;i++)	res[i]=i;
            mergesortIndex(res,a,0,a.length);
            return res;
        }
        private static Integer[] stem=new Integer[200005];
        private static void mergesortIndex(Integer[] index,long[] a, int s, int e){//uwi's
            if(e - s <= 1)return;
            int h = s+e>>1;
            mergesortIndex(index,a, s, h);
            mergesortIndex(index,a, h, e);
            int p = 0;
            int i= s, j = h;
            for(;i < h && j < e;)stem[p++] = a[(int)index[i]] < a[(int)index[j]] ? index[i++] : index[j++];
            while(i < h)stem[p++] = index[i++];
            while(j < e)stem[p++] = index[j++];
            System.arraycopy(stem, 0, index, s, e-s);
        }
        private static long[] stmp=new long[200005];
        private static void mergesort(long[] a, int s, int e){//uwi's
            if(e - s <= 1)return;
            int h = s+e>>1;
            mergesort(a, s, h);
            mergesort(a, h, e);
            int p = 0;
            int i= s, j = h;
            for(;i < h && j < e;)stmp[p++] = a[i] < a[j] ? a[i++] : a[j++];
            while(i < h)stmp[p++] = a[i++];
            while(j < e)stmp[p++] = a[j++];
            System.arraycopy(stmp, 0, a, s, e-s);
        }
}

import java.io.IOException;
import java.util.HashMap;
import java.util.NoSuchElementException;

public class Main{
	static int mod = 1000000007;
	static HashMap<Long,Long> map=new HashMap<Long,Long>();
	static long M;
	public static void main(String[] args){

		FastScanner sc = new FastScanner();
		long N = sc.nextLong();
		M = sc.nextLong();
		System.out.println(dp(N));
	}
	private static long dp(long n) {
		if(map.containsKey(n)){
			return map.get(n);
		}else{
			if(n<M){
				return 1;
			}
			long l = n/2;
			long r = n%2==0?n/2:n/2+1;
			long ans = dp(l)*dp(r);
			for(int i=1;i<M;i++){
				if(l-i>=0&&r-(M-i)>=0){
					ans += dp(l-i) * dp(r-(M-i));
					ans %= mod;
				}
			}
			ans %= mod;
			map.put(n,ans);
			return ans;
		}
	}

}

class FastScanner {
    private final java.io.InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;
    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        }else{
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }
    private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
    private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
    private void skipUnprintable() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++;}
    public boolean hasNext() { skipUnprintable(); return hasNextByte();}
    public String next() {
        if (!hasNext()) throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while(isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }
    public long nextLong() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return (minus ? -n : n);
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
    public int nextInt() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return (int) (minus ? -n : n);
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
}

import java.util.*;

import java.io.*;
import java.math.BigInteger;

public class D {
	FastScanner in;
	PrintWriter out;
	boolean systemIO = true;

	public class Pair implements Comparable<Pair> {
		long x;
		long y;

		public Pair(long x, long y) {
			this.x = x;
			this.y = y;
		}

		@Override
		public int compareTo(Pair o) {
			if (x > o.x) {
				return 1;
			}
			if (x < o.x) {
				return -1;
			}
			if (y > o.y) {
				return 1;
			}
			if (y < o.y) {
				return -1;
			}
			return 0;
		}

	}

	public class Fenvik {
		int[] sum;

		public Fenvik(int n) {
			sum = new int[n];
		}

		public void add(int x, int d) {
			for (int i = x; i < sum.length; i = (i | (i + 1))) {
				sum[i] += d;
			}
		}

		public int sum(int r) {
			int ans = 0;
			for (int i = r; i >= 0; i = (i & (i + 1)) - 1) {
				ans += sum[i];
			}
			return ans;
		}

		public int sum(int l, int r) {
			if (l > r) {
				return 0;
			}
			return sum(r) - sum(l - 1);
		}
	}

	public long gcd(long x, long y) {
		if (y == 0) {
			return x;
		}
		if (x == 0) {
			return y;
		}
		return gcd(y, x % y);
	}

	public long[][] pow(long[][] x, long p) {
		if (p == 0) {
			long[][] ans = new long[m][m];
			for (int i = 0; i < ans.length; i++) {
				ans[i][i] = 1;
			}
			return ans;
		}
		long[][] t = pow(x, p / 2);
		t = multiply(t, t);
		if (p % 2 == 1) {
			t = multiply(t, x);
		}
		return t;
	}

	public long[][] multiply(long[][] a, long[][] b) {
		long[][] ans = new long[a.length][b[0].length];
		for (int i = 0; i < ans.length; i++) {
			for (int j = 0; j < ans[0].length; j++) {
				for (int k = 0; k < b.length; k++) {
					ans[i][j] += a[i][k] * b[k][j];
					ans[i][j] %= mod;
				}
			}
		}
		return ans;
	}

	long mod = 1000000007;
	int m;

	public void solve() {
		long n = in.nextLong();
		m = in.nextInt();
		long[][] a = new long[m][m];
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j <= i; j++) {
				a[i][j]++;
			}
			a[i][m - 1]++;
		}
		long[][] th = new long[m][1];
		for (int i = 0; i < th.length; i++) {
			th[i][0] = 1 + (i + 1) / m;
		}
		a = pow(a, (n - 1) / m);
		th = multiply(a, th);
		out.println(th[(int) ((n - 1) % m)][0]);
	}

	public void run() {
		try {
			if (systemIO) {
				in = new FastScanner(System.in);
				out = new PrintWriter(System.out);
			} else {
				in = new FastScanner(new File("input.txt"));
				out = new PrintWriter(new File("output.txt"));
			}
			solve();

			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner(File f) {
			try {
				br = new BufferedReader(new FileReader(f));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}

		FastScanner(InputStream f) {
			br = new BufferedReader(new InputStreamReader(f));
		}

		String nextLine() {
			try {
				return br.readLine();
			} catch (IOException e) {
				return null;
			}
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

		int nextInt() {
			return Integer.parseInt(next());
		}

		long nextLong() {
			return Long.parseLong(next());
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}

	}

	// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	public static void main(String[] arg) {
		new D().run();
	}
}

import java.util.*;
import java.io.*;

public class Main {
	public static void main(String args[]) {new Main().run();}

	FastReader in = new FastReader();
	PrintWriter out = new PrintWriter(System.out);
	void run(){
		out.println(work());
		out.flush();
	}
	long mod=1000000007;
	long work() {
		long n=in.nextLong();
		int m=in.nextInt();
		long[][] matrix=new long[m][m];
		long[] ret=new long[m];
		Arrays.fill(ret, 1);
		matrix[0][0]=1;//初始条件
		matrix[0][m-1]=1;
		for(int i=1;i<m;i++) {
			matrix[i][i-1]=1;
		}
		long t=n-m+1;
		while(true) {
			if(t%2==1) {
				long[] nret=new long[m];
				for(int i=0;i<m;i++) {
					for(int j=0;j<m;j++) {
						nret[i]+=ret[j]*matrix[i][j];
						nret[i]%=mod;
					}
				}
				ret=nret;
			}
			t/=2;
			if(t==0) break;
			long[][] nmatrix=new long[m][m];
			for(int i=0;i<m;i++) {
				for(int j=0;j<m;j++) {
					for(int k=0;k<m;k++) {
						nmatrix[i][j]+=matrix[i][k]*matrix[k][j];
						nmatrix[i][j]%=mod;
					}
				}
			}
			matrix=nmatrix;
		}
		return ret[0];
	}
}

class FastReader
{
	BufferedReader br;
	StringTokenizer st;

	public FastReader()
	{
		br=new BufferedReader(new InputStreamReader(System.in));
	}

	public String next()
	{
		if(st==null || !st.hasMoreElements())
		{
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return st.nextToken();
	}

	public int nextInt()
	{
		return Integer.parseInt(next());
	}

	public long nextLong()
	{
		return Long.parseLong(next());
	}
}

import java.io.*;
import java.text.*;
import java.util.*;
import java.math.*;
public class template {
	public static void main(String[] args) throws Exception {
		new template().run();
	}
	public void run() throws Exception {
		FastScanner f = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		long n = f.nextLong();
		int m = f.nextInt();
		long[][] mult = new long[m][m];
		for(int i = 1; i < m; i++)
			mult[i][i-1] = 1;
		mult[0][0] = mult[0][m-1] = 1;
		long[][] start = new long[1][m];
		start[0][0] = 1;
		start = mult(start,exp(mult,n));
		out.println(start[0][0]);
		out.flush();
	}
	public long[][] exp(long[][] a, long exp) {
		if(exp == 1) return a;
		long[][] res = exp(a, exp >> 1);
		res = mult(res,res);
		if((exp & 1) == 1) res = mult(res,a);
		return res;
	}
	public static final long MOD = 1_000_000_007;
	public long[][] mult(long[][] a, long[][] b) {
		long[][] c = new long[a.length][b[0].length];
		for(int i = 0; i < a.length; i++)
			for(int j = 0; j < b[0].length; j++)
				for(int k = 0; k < a[0].length; k++)
					c[i][j] = (c[i][j] + a[i][k] * b[k][j] % MOD) % MOD;
		return c;
	}
    static class FastScanner {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public FastScanner() {
            reader = new BufferedReader(new InputStreamReader(System.in), 32768);
            tokenizer = null;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
        	return Long.parseLong(next());
        }
        public double nextDouble() {
        	return Double.parseDouble(next());
        }
        public String nextLine() {
        	try {
        		return reader.readLine();
        	} catch(IOException e) {
        		throw new RuntimeException(e);
        	}
        }
    }
}

import java.util.*;
import java.io.*;

public class template {
	final static int MOD = 1000000007;
	final static int intMax = 1000000000;
	final static int intMin = -1000000000;
	final static int[] dx = { 0, 0, -1, 1 };
	final static int[] dy = { -1, 1, 0, 0 };

	static int T;

	static class Reader {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;

		public Reader() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public Reader(String file_name) throws IOException {
			din = new DataInputStream(new FileInputStream(file_name));
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public String readLine() throws IOException {
			byte[] buf = new byte[360]; // line length
			int cnt = 0, c;
			while ((c = read()) != -1) {
				if (c == '\n')
					break;
				buf[cnt++] = (byte) c;
			}
			return new String(buf, 0, cnt);
		}

		public int nextInt() throws IOException {
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');

			if (neg)
				return -ret;
			return ret;
		}

		public long nextLong() throws IOException {
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}

		public double nextDouble() throws IOException {
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();

			do {
				ret = ret * 10 + c - '0';
			} while ((c = read()) >= '0' && c <= '9');

			if (c == '.') {
				while ((c = read()) >= '0' && c <= '9') {
					ret += (c - '0') / (div *= 10);
				}
			}

			if (neg)
				return -ret;
			return ret;
		}

		private void fillBuffer() throws IOException {
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}

		private byte read() throws IOException {
			if (bufferPointer == bytesRead)
				fillBuffer();
			return buffer[bufferPointer++];
		}

		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}

	static long[][] X;
	static long N;
	static int M;

	static long[][] mult(long[][] a, long[][] b){
		long[][] ans = new long[M][M];
		for(int i = 0; i < M; ++i) {
			for(int k = 0; k < M; ++k) {
				for(int j = 0; j < M; ++j) {
					ans[i][j] = (ans[i][j] + a[i][k] * b[k][j]) % MOD;
				}
			}
		}
		return ans;
	}

	static long[][] exp(long[][] mat, long exponent) {
		--exponent;
		long[][] ans = X.clone();
		while (exponent > 0) {
			if ((exponent & 1) > 0) {
				ans = mult(ans, mat);
			}
			mat = mult(mat, mat);
			exponent >>= 1;
		}
		return ans;
	}

	public static void main(String[] args) throws Exception {
		Reader in = new Reader();
		N = in.nextLong();
		M = in.nextInt();
		if(N < M) {
			System.out.println(1);
		}
		else {
			X = new long[M][M];
			X[0][0] = X[0][M - 1] = 1;
			for(int i = 1; i < M; ++i) {
				X[i][i - 1] = 1;
			}
			long[][] init = X.clone();
			long[][] ans = exp(init, N);
			System.out.println(ans[0][0]);
		}
		in.close();
	}
}

import java.lang.*;
import java.math.*;
import java.util.*;
import java.io.*;

public class Main {
    void solve() {
       long n=nl(); m=ni();
       long Mat[][]=new long[m+2][m+2];
       Mat[1][1]=1; Mat[m][1]=1;
       long f[]=new long[m+1];

       f[0]=1;
       for(int i=1;i<=m;i++){
           f[i]=f[i-1];
           if(i-m>=0) f[i]=add(f[i],f[i-m]);
       }
       if(n<=m){
           pw.println(f[(int)n]);
           return;
       }
       for(int j=2;j<=m+1;j++){
           Mat[j-1][j]=1;
       }
       Mat=pow(Mat,n-m);
        long ans=0;
        for(int i=1;i<=m+1;i++){
            ans=add(ans,mul(Mat[i][1],f[m-i+1]));
        }
        pw.println(ans);

    }
    int m;
    long [][] pow(long A[][],long x){
        if(x==0){
            long C[][]=new long[m+2][m+2];
            for(int i=1;i<=m+1;i++) C[i][i]=1;
            return C;
        }else if(x==1){
            return A;
        }
        long C[][]=pow(A,x/2);
        C=mul(C,C);
        if((x&1)>0) return mul(A,C);
        return C;

    }
    long [][] mul(long A[][],long B[][]){
        long C[][]=new long[m+2][m+2];
        for(int i=1;i<=m+1;i++){
            for(int j=1;j<=m+1;j++){
                for(int k=1;k<=m+1;k++){
                    C[i][j]=add(C[i][j],mul(A[i][k],B[k][j]));
                }
            }
        }
        return C;
    }
    long[][] modpow(long A[][], long b)
    {
        long C[][]=new long[m+2][m+2];
        for(int i=1;i<=m+1;i++) C[i][i]=1;
        while(b>0)
        {
            if((b&1)>0) C=mul(C,A);
            A=mul(A,A);
            b>>=1;
        }
        return C;
    }
    long add(long a,long b){
        a+=b;
        if(a>=M) a-=M;
        return a;
    }
    long mul(long a,long b){
        a*=b;
        if(a>=M )a%=M;
        return a;
    }

    static int randInt(int min,int max){
        Random rand=new Random();
        int randInt=rand.nextInt((max-min)+1)+min;
        return randInt;
    }

    long M = (long)1e9+7;
    InputStream is;
    PrintWriter pw;
    String INPUT = "";

    void run() throws Exception {
        is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        pw = new PrintWriter(System.out);
        long s = System.currentTimeMillis();
        solve();
        pw.flush();
        if (!INPUT.isEmpty()) tr(System.currentTimeMillis() - s + "ms");

    }

    public static void main(String[] args) throws Exception {
        new Main().run();
    }

    private byte[] inbuf = new byte[1024];
    public int lenbuf = 0, ptrbuf = 0;

    private int readByte() {
        if (lenbuf == -1) throw new InputMismatchException();
        if (ptrbuf >= lenbuf) {
            ptrbuf = 0;
            try {
                lenbuf = is.read(inbuf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (lenbuf <= 0) return -1;
        }
        return inbuf[ptrbuf++];
    }

    private boolean isSpaceChar(int c) {
        return !(c >= 33 && c <= 126);
    }

    private int skip() {
        int b;
        while ((b = readByte()) != -1 && isSpaceChar(b)) ;
        return b;
    }

    private double nd() {
        return Double.parseDouble(ns());
    }

    private char nc() {
        return (char) skip();
    }

    private String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    private char[] ns(int n) {
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while (p < n && !(isSpaceChar(b))) {
            buf[p++] = (char) b;
            b = readByte();
        }
        return n == p ? buf : Arrays.copyOf(buf, p);
    }

    private char[][] nm(int n, int m) {
        char[][] map = new char[n][];
        for (int i = 0; i < n; i++) map[i] = ns(m);
        return map;
    }

    private int[] na(int n) {
        int[] a = new int[n];
        for (int i = 0; i < n; i++) a[i] = ni();
        return a;
    }

    private int ni() {
        int num = 0, b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
        if (b == '-') {
            minus = true;
            b = readByte();
        }

        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private long nl() {
        long num = 0;
        int b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
        if (b == '-') {
            minus = true;
            b = readByte();
        }

        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private boolean oj = System.getProperty("ONLINE_JUDGE") != null;

    private void tr(Object... o) {
        if (INPUT.length() > 0) System.out.println(Arrays.deepToString(o));
    }

}

import java.lang.*;
import java.math.*;
import java.util.*;
import java.io.*;

public class Main {
    void solve() {
       long n=nl(); m=ni();
       long Mat[][]=new long[m+2][m+2];
       Mat[1][1]=1; Mat[m][1]=1;
       long f[]=new long[m+1];

       f[0]=1;
       for(int i=1;i<=m;i++){
           f[i]=f[i-1];
           if(i-m>=0) f[i]=add(f[i],f[i-m]);
       }
       if(n<=m){
           pw.println(f[(int)n]);
           return;
       }
       for(int j=2;j<=m+1;j++){
           Mat[j-1][j]=1;
       }
       Mat=modpow(Mat,n-m);
        long ans=0;
        for(int i=1;i<=m+1;i++){
            ans=add(ans,mul(Mat[i][1],f[m-i+1]));
        }
        pw.println(ans);

    }
    int m;
    long [][] pow(long A[][],long x){
        if(x==0){
            long C[][]=new long[m+2][m+2];
            for(int i=1;i<=m+1;i++) C[i][i]=1;
            return C;
        }else if(x==1){
            return A;
        }
        long C[][]=pow(A,x/2);
        C=mul(C,C);
        if((x&1)>0) return mul(A,C);
        return C;

    }
    long [][] mul(long A[][],long B[][]){
        long C[][]=new long[m+2][m+2];
        for(int i=1;i<=m+1;i++){
            for(int j=1;j<=m+1;j++){
                for(int k=1;k<=m+1;k++){
                    C[i][j]=add(C[i][j],mul(A[i][k],B[k][j]));
                }
            }
        }
        return C;
    }
    long[][] modpow(long A[][], long b)
    {
        long C[][]=new long[m+2][m+2];
        for(int i=1;i<=m+1;i++) C[i][i]=1;
        while(b>0)
        {
            if((b&1)>0) C=mul(C,A);
            A=mul(A,A);
            b>>=1;
        }
        return C;
    }
    long add(long a,long b){
        a+=b;
        if(a>=M) a-=M;
        return a;
    }
    long mul(long a,long b){
        a*=b;
        if(a>=M )a%=M;
        return a;
    }

    static int randInt(int min,int max){
        Random rand=new Random();
        int randInt=rand.nextInt((max-min)+1)+min;
        return randInt;
    }

    long M = (long)1e9+7;
    InputStream is;
    PrintWriter pw;
    String INPUT = "";

    void run() throws Exception {
        is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        pw = new PrintWriter(System.out);
        long s = System.currentTimeMillis();
        solve();
        pw.flush();
        if (!INPUT.isEmpty()) tr(System.currentTimeMillis() - s + "ms");

    }

    public static void main(String[] args) throws Exception {
        new Main().run();
    }

    private byte[] inbuf = new byte[1024];
    public int lenbuf = 0, ptrbuf = 0;

    private int readByte() {
        if (lenbuf == -1) throw new InputMismatchException();
        if (ptrbuf >= lenbuf) {
            ptrbuf = 0;
            try {
                lenbuf = is.read(inbuf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (lenbuf <= 0) return -1;
        }
        return inbuf[ptrbuf++];
    }

    private boolean isSpaceChar(int c) {
        return !(c >= 33 && c <= 126);
    }

    private int skip() {
        int b;
        while ((b = readByte()) != -1 && isSpaceChar(b)) ;
        return b;
    }

    private double nd() {
        return Double.parseDouble(ns());
    }

    private char nc() {
        return (char) skip();
    }

    private String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    private char[] ns(int n) {
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while (p < n && !(isSpaceChar(b))) {
            buf[p++] = (char) b;
            b = readByte();
        }
        return n == p ? buf : Arrays.copyOf(buf, p);
    }

    private char[][] nm(int n, int m) {
        char[][] map = new char[n][];
        for (int i = 0; i < n; i++) map[i] = ns(m);
        return map;
    }

    private int[] na(int n) {
        int[] a = new int[n];
        for (int i = 0; i < n; i++) a[i] = ni();
        return a;
    }

    private int ni() {
        int num = 0, b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
        if (b == '-') {
            minus = true;
            b = readByte();
        }

        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private long nl() {
        long num = 0;
        int b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
        if (b == '-') {
            minus = true;
            b = readByte();
        }

        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private boolean oj = System.getProperty("ONLINE_JUDGE") != null;

    private void tr(Object... o) {
        if (INPUT.length() > 0) System.out.println(Arrays.deepToString(o));
    }

}

// package Practice.CF1117;

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class CF1117D {
    static FastReader s;
    static PrintWriter out;
    static String INPUT = "1 3\n";
    static int mod = 1000_000_007;
    static long[][] I;

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
        out = new PrintWriter(System.out);
        s = new FastReader(oj);
        long n = s.nextLong();
        int m = s.nextInt();
        long[][] arr = new long[m][m];
        I = new long[m][m];
        arr[m - 1][0] = 1L;
        arr[m - 1][m - 1] = 1L;
        for (int i = 0; i < m - 1; i++) {
            arr[i][i + 1] = 1L;
            I[i][i] = 1L;
        }
        I[m - 1][m - 1] = 1L;
        long[][] fArr = new long[m][1];
        for (int i = 0; i < m; i++) {
            fArr[i][0] = 1L;
        }

        long[][] ans = Matrix.mult(Matrix.exp(arr, n - m + 1), fArr);
        out.println(ans[ans.length - 1][ans[0].length - 1] % mod);

        if (!oj) {
            System.out.println(Arrays.deepToString(new Object[]{System.currentTimeMillis() - time + " ms"}));
        }
        out.flush();
    }

    private static class Matrix {

        public static long[][] exp(long[][] M, long n) {
            if (n <= 0) return I;
            if (n == 1) return M;
            long[][] res = exp(M, n / 2);
            res = mult(res, res);
            if (n % 2 == 0) return res;
            return mult(res, M);
        }

        public static long[][] mult(long[][] p, long[][] q) {
            long[][] r = new long[p.length][q[0].length];
            for (int i = 0; i < p.length; i++)
                for (int j = 0; j < q[0].length; j++)
                    for (int k = 0; k < q.length; k++) {
                        r[i][j] += p[i][k] * q[k][j];
                        r[i][j] %= mod;
                    }
            return r;
        }
    }

    private static class Maths {
        static ArrayList<Long> printDivisors(long n) {
            // Note that this loop runs till square root
            ArrayList<Long> list = new ArrayList<>();
            for (long i = 1; i <= Math.sqrt(n); i++) {
                if (n % i == 0) {
                    if (n / i == i) {
                        list.add(i);
                    } else {
                        list.add(i);
                        list.add(n / i);
                    }
                }
            }
            return list;
        }

        //    GCD - Using Euclid theorem.
        private static long gcd(long a, long b) {
            if (b == 0) {
                return a;
            }

            return gcd(b, a % b);
        }

        //    Extended euclidean algorithm
//    Used to solve equations of the form ax + by = gcd(a,b)
//    return array [d, a, b] such that d = gcd(p, q), ap + bq = d
        static long[] extendedEuclidean(long p, long q) {
            if (q == 0)
                return new long[]{p, 1, 0};

            long[] vals = extendedEuclidean(q, p % q);
            long d = vals[0];
            long a = vals[2];
            long b = vals[1] - (p / q) * vals[2];
            return new long[]{d, a, b};
        }

        // X ^ y mod p
        static long power(long x, long y, long p) {
            long res = 1;
            x = x % p;

            while (y > 0) {
                if ((y & 1) == 1)
                    res = (res * x) % p;
                y = y >> 1;
                x = (x * x) % p;
            }
            return res;
        }

        // Returns modulo inverse of a
        // with respect to m using extended
        // Euclid Algorithm. Refer below post for details:
        // https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/
        static long inv(long a, long m) {
            long m0 = m, t, q;
            long x0 = 0, x1 = 1;

            if (m == 1)
                return 0;

            // Apply extended Euclid Algorithm
            while (a > 1) {
                q = a / m;
                t = m;
                m = a % m;
                a = t;
                t = x0;
                x0 = x1 - q * x0;
                x1 = t;
            }

            // Make x1 positive
            if (x1 < 0)
                x1 += m0;

            return x1;
        }

        // k is size of num[] and rem[].
        // Returns the smallest number
        // x such that:
        // x % num[0] = rem[0],
        // x % num[1] = rem[1],
        // ..................
        // x % num[k-2] = rem[k-1]
        // Assumption: Numbers in num[] are pairwise
        // coprime (gcd for every pair is 1)
        static long findMinX(long num[], long rem[], long k) {
            int prod = 1;
            for (int i = 0; i < k; i++)
                prod *= num[i];

            int result = 0;
            for (int i = 0; i < k; i++) {
                long pp = prod / num[i];
                result += rem[i] * inv(pp, num[i]) * pp;
            }

            return result % prod;
        }
    }

    private static class BS {
        //  Binary search
        private static int binarySearch(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    return mid;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return -1;
        }

        //    First occurence using binary search
        private static int binarySearchFirstOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    high = mid - 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }

        //    Last occurenece using binary search
        private static int binarySearchLastOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    low = mid + 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }
    }

    private static class arrays {
        // Merge sort
        static void merge(int arr[], int l, int m, int r) {
            int n1 = m - l + 1;
            int n2 = r - m;
            int L[] = new int[n1];
            int R[] = new int[n2];
            for (int i = 0; i < n1; ++i)
                L[i] = arr[l + i];
            for (int j = 0; j < n2; ++j)
                R[j] = arr[m + 1 + j];
            int i = 0, j = 0;
            int k = l;
            while (i < n1 && j < n2) {
                if (L[i] <= R[j]) {
                    arr[k] = L[i];
                    i++;
                } else {
                    arr[k] = R[j];
                    j++;
                }
                k++;
            }

            while (i < n1) {
                arr[k] = L[i];
                i++;
                k++;
            }

            while (j < n2) {
                arr[k] = R[j];
                j++;
                k++;
            }
        }

        static void sort(int arr[], int l, int r) {
            if (l < r) {
                int m = (l + r) / 2;
                sort(arr, l, m);
                sort(arr, m + 1, r);
                merge(arr, l, m, r);
            }
        }

        static void sort(int[] arr) {
            sort(arr, 0, arr.length - 1);
        }
    }

    private static class UnionFindDisjointSet {
        int[] parent;
        int[] size;
        int n;
        int size1;

        public UnionFindDisjointSet(int n) {
            this.n = n;
            this.parent = new int[n];
            this.size = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }

            for (int i = 0; i < n; i++) {
                size[i] = 1;
            }

            this.size1 = n;
        }

        private int numDisjointSets() {
            System.out.println(size1);
            return size1;
        }

        private boolean find(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return true;
            }
            return false;
        }

        private int root(int b) {
            while (parent[b] != b) {
                parent[b] = parent[parent[b]];
                b = parent[b];
            }
            return b;
        }

        private void union(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return;
            }

            if (size[rootA] < size[rootB]) {
                parent[rootA] = parent[rootB];
                size[rootB] += size[rootA];
            } else {
                parent[rootB] = parent[rootA];
                size[rootA] += size[rootB];
            }
            size1--;
            System.out.println(Arrays.toString(parent));
        }
    }

    private static class SegTree {
        int[] st;
        int[] arr;

        public SegTree(int[] arr) {
            this.arr = arr;
            int size = (int) Math.ceil(Math.log(arr.length) / Math.log(2));
            st = new int[(int) ((2 * Math.pow(2, size)) - 1)];
            buildSegmentTree(1, 0, arr.length - 1);
        }

        //**********JUST CALL THE CONSTRUCTOR, THIS FUNCTION WILL BE CALLED AUTOMATICALLY******
        private void buildSegmentTree(int index, int L, int R) {
            if (L == R) {
                st[index] = arr[L];
                return;
            }

            buildSegmentTree(index * 2, L, (L + R) / 2);
            buildSegmentTree(index * 2 + 1, (L + R) / 2 + 1, R);
//          Replace this line if you want to change the function of the Segment tree.
            st[index] = Math.min(st[index * 2], st[index * 2 + 1]);
        }

        //***********We have to use this function **************
        private int Query(int queL, int queR) {
            return Query1(1, 0, arr.length - 1, queL, queR);
        }

        //This is a helper function.
        //************* DO NOT USE THIS ****************
        private int Query1(int index, int segL, int segR, int queL, int queR) {
            if (queL > segR || queR < segL) {
                return -1;
            }

            if (queL <= segL && queR >= segR) {
                return st[index];
            }

            int ans1 = Query1(index * 2, segL, (segL + segR) / 2, queL, queR);
            int ans2 = Query1(index * 2 + 1, (segL + segR) / 2 + 1, segR, queL, queR);
            if (ans1 == -1) {
                return ans2;
            }

            if (ans2 == -1) {
                return ans1;
            }
//             Segment tree implemented for range minimum query. Change the below line to change the function.
            return Math.min(ans1, ans2);
        }

        private void update(int idx, int val) {
            update1(1, 0, arr.length - 1, idx, val);
        }

        private void update1(int node, int queL, int queR, int idx, int val) {
            // idx - index to be updated in the array
            // node - index to be updated in the seg tree
            if (queL == queR) {
                // Leaf node
                arr[idx] += val;
                st[node] += val;
            } else {
                int mid = (queL + queR) / 2;
                if (queL <= idx && idx <= mid) {
                    // If idx is in the left child, recurse on the left child
                    update1(2 * node, queL, mid, idx, val);
                } else {
                    // if idx is in the right child, recurse on the right child
                    update1(2 * node + 1, mid + 1, queR, idx, val);
                }
                // Internal node will have the min of both of its children
                st[node] = Math.min(st[2 * node], st[2 * node + 1]);
            }
        }

    }

    private static class FastReader {
        InputStream is;

        public FastReader(boolean onlineJudge) {
            is = onlineJudge ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        }

        byte[] inbuf = new byte[1024];
        public int lenbuf = 0, ptrbuf = 0;

        int readByte() {
            if (lenbuf == -1)
                throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0)
                    return -1;
            }
            return inbuf[ptrbuf++];
        }

        boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b))
                ;
            return b;
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        char nextChar() {
            return (char) skip();
        }

        String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        String nextLine() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while ((!isSpaceChar(b) || b == ' ')) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        char[][] nextMatrix(int n, int m) {
            char[][] map = new char[n][];
            for (int i = 0; i < n; i++)
                map[i] = next(m);
            return map;
        }

        int[] nextIntArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        long[] nextLongArray(int n) {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
                a[i] = nextLong();
            return a;
        }

        int[][] next2DInt(int n, int m) {
            int[][] arr = new int[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextIntArray(m);
            }
            return arr;
        }

        long[][] next2DLong(int n, int m) {
            long[][] arr = new long[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLongArray(m);
            }
            return arr;
        }

        int[] shuffle(int[] arr) {
            Random r = new Random();
            for (int i = 1, j; i < arr.length; i++) {
                j = r.nextInt(i);
                arr[i] = arr[i] ^ arr[j];
                arr[j] = arr[i] ^ arr[j];
                arr[i] = arr[i] ^ arr[j];
            }
            return arr;
        }

        int[] uniq(int[] arr) {
            Arrays.sort(arr);
            int[] rv = new int[arr.length];
            int pos = 0;
            rv[pos++] = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if (arr[i] != arr[i - 1]) {
                    rv[pos++] = arr[i];
                }
            }
            return Arrays.copyOf(rv, pos);
        }
    }

}

import java.io.*;
import java.util.*;
public class  Main{
	static int mod=(int)1e9+7;
	/*
	 * 3. Matrix Multiplication
	 */
	static int[][] matMul(int[][] A, int[][] B, int p, int q, int r)	//C(p x r) = A(p x q) x (q x r) -- O(p x q x r)
	{
		int[][] C = new int[p][r];
		for(int i = 0; i < p; ++i)
			for(int j = 0; j < r; ++j)
				for(int k = 0; k < q; ++k) {
					C[i][j] = (int)(C[i][j]+(A[i][k] *1l* B[k][j])%mod)%mod;
				}
		return C;
	}

	/*
	 * 4. Square Matrix Exponentiation
	 */
	static int[][] matPow(int[][] base, long p)
	{
		int n = base.length;
		int[][] ans = new int[n][n];
		for(int i = 0; i < n; i++)
			ans[i][i] = 1;
		while(p != 0)
		{
			if((p & 1) == 1)
				ans = matMul(ans, base, n, n, n);
			base = matMul(base, base, n, n, n);
			p >>= 1;
		}

		return ans;
	}
	public static void main(String[] args) throws Exception{
		MScanner sc=new MScanner(System.in);
		PrintWriter pw=new PrintWriter(System.out);
		long n=sc.nextLong();
		int m=sc.nextInt();
		int[][]base=new int[m][1];
		for(int i=0;i<m-1;i++)base[i][0]=1;
		base[m-1][0]=2;
		int[][]t=new int[m][m];
		for(int i=0;i<m-1;i++) {
			t[i][i+1]=1;
		}
		t[m-1][0]=1;
		t[m-1][m-1]=1;
		t=matPow(t, n-1);
		int[][]res=matMul(t, base, m, m, 1);
		pw.println(res[0][0]);
		pw.flush();
	}
	static class MScanner {
		StringTokenizer st;
		BufferedReader br;
		public MScanner(InputStream system) {
			br = new BufferedReader(new InputStreamReader(system));
		}

		public MScanner(String file) throws Exception {
			br = new BufferedReader(new FileReader(file));
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}
		public int[] takearr(int n) throws IOException {
	        int[]in=new int[n];for(int i=0;i<n;i++)in[i]=nextInt();
	        return in;
		}
		public long[] takearrl(int n) throws IOException {
	        long[]in=new long[n];for(int i=0;i<n;i++)in[i]=nextLong();
	        return in;
		}
		public Integer[] takearrobj(int n) throws IOException {
	        Integer[]in=new Integer[n];for(int i=0;i<n;i++)in[i]=nextInt();
	        return in;
		}
		public Long[] takearrlobj(int n) throws IOException {
	        Long[]in=new Long[n];for(int i=0;i<n;i++)in[i]=nextLong();
	        return in;
		}
		public String nextLine() throws IOException {
			return br.readLine();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		public double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}

		public char nextChar() throws IOException {
			return next().charAt(0);
		}

		public Long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public boolean ready() throws IOException {
			return br.ready();
		}

		public void waitForInput() throws InterruptedException {
			Thread.sleep(3000);
		}
	}
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DMagicGems solver = new DMagicGems();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems {
        int mod = (int) 1e9 + 7;

        private long[][] multiply(long[][] mat, long[][] mul) {
            long[][] res = new long[mat.length][mul[0].length];
            int n = mat.length, m = mul[0].length, o = mul.length;
            for (int i = 0; i < n; i++)
                for (int j = 0; j < m; j++)
                    for (int k = 0; k < o; k++) {
                        res[i][j] += mat[i][k] * mul[k][j] % mod;
                        res[i][j] %= mod;
                    }
            return res;
        }

        public void solve(int testNumber, Scanner sc, PrintWriter pw) {
            long n = sc.nextLong();
            int m = sc.nextInt();
            long[][] mat = new long[m][m];
            for (int i = 0; i < m - 1; i++)
                for (int j = 0; j < m; j++)
                    if (i + 1 == j)
                        mat[i][j] = 1;
            mat[m - 1][0] = 1;
            mat[m - 1][m - 1] = 1;
            long[][] ans = new long[m][m];
            for (int i = 0; i < m; i++)
                ans[i][i] = 1;
            while (n > 0) {
                if (n % 2 == 1) {
                    ans = multiply(ans, mat);
                }
                mat = multiply(mat, mat);
                n /= 2;
            }
            long[][] temp = new long[m][1];
            for (int i = 0; i < m; i++) {
                temp[i][0] = 1;
            }
            long[][] ans2 = multiply(ans, temp);
            pw.println(ans2[0][0]);
        }

    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(FileReader r) {
            br = new BufferedReader(r);
        }

        public Scanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }
}

import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;

public class cf1117d_2 {

    public static void main(String[] args) throws IOException {
        long n = rnl();
        int m = ni(), mat[][] = new int[m][m];
        mat[0][0] = mat[0][m - 1] = 1;
        for (int i = 1; i < m; ++i) {
            mat[i][i - 1] = 1;
        }
        if (n < m) {
            prln(1);
        } else {
            prln(fpowmat(mat, n)[0][0]);
        }
        close();
    }

    static int[][] fpowmat(int[][] a, long b) {
        return fpowmat(a, b, IBIG);
    }

    static int[][] fpowmat(int[][] a, long b, int mod) {
        assert a.length > 0 && a.length == a[0].length;
        int n = a.length, ans[][] = new int[n][n];
        for (int i = 0; i < n; ++i) {
            ans[i][i] = 1;
        }
        while (b > 0) {
            if ((b & 1) > 0) {
                ans = mulmat(ans, a, mod);
            }
            a = mulmat(a, a, mod);
            b >>= 1;
        }
        return ans;
    }

    static int[][] mulmat(int[][] a, int[][] b) {
        return mulmat(a, b, IBIG);
    }

    static int[][] mulmat(int[][] a, int[][] b, int mod) {
        assert a.length > 0 && a[0].length > 0 && b.length > 0 && b[0].length > 0 && a[0].length == b.length;
        int m = a.length, n = a[0].length, p = b[0].length, ans[][] = new int[a.length][b[0].length];
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < p; ++j) {
                for (int k = 0; k < n; ++k) {
                    ans[i][j] = (int) ((ans[i][j] + (long) a[i][k] * b[k][j]) % mod);
                }
            }
        }
        return ans;
    }

    static BufferedReader __in = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter __out = new PrintWriter(new OutputStreamWriter(System.out));
    static StringTokenizer input;
    static Random __rand = new Random();

    // references
    // IBIG = 1e9 + 7
    // IMAX ~= 2e9
    // LMAX ~= 9e18

    // constants
    static final int IBIG = 1000000007;
    static final int IMAX = 2147483647;
    static final int IMIN = -2147483648;
    static final long LMAX = 9223372036854775807L;
    static final long LMIN = -9223372036854775808L;
    // math util
    static int minof(int a, int b, int c) {return min(a, min(b, c));}
    static int minof(int... x) {if (x.length == 1) return x[0]; if (x.length == 2) return min(x[0], x[1]); if (x.length == 3) return min(x[0], min(x[1], x[2])); int min = x[0]; for (int i = 1; i < x.length; ++i) if (x[i] < min) min = x[i]; return min;}
    static long minof(long a, long b, long c) {return min(a, min(b, c));}
    static long minof(long... x) {if (x.length == 1) return x[0]; if (x.length == 2) return min(x[0], x[1]); if (x.length == 3) return min(x[0], min(x[1], x[2])); long min = x[0]; for (int i = 1; i < x.length; ++i) if (x[i] < min) min = x[i]; return min;}
    static int maxof(int a, int b, int c) {return max(a, max(b, c));}
    static int maxof(int... x) {if (x.length == 1) return x[0]; if (x.length == 2) return max(x[0], x[1]); if (x.length == 3) return max(x[0], max(x[1], x[2])); int max = x[0]; for (int i = 1; i < x.length; ++i) if (x[i] > max) max = x[i]; return max;}
    static long maxof(long a, long b, long c) {return max(a, max(b, c));}
    static long maxof(long... x) {if (x.length == 1) return x[0]; if (x.length == 2) return max(x[0], x[1]); if (x.length == 3) return max(x[0], max(x[1], x[2])); long max = x[0]; for (int i = 1; i < x.length; ++i) if (x[i] > max) max = x[i]; return max;}
    static int powi(int a, int b) {if (a == 0) return 0; int ans = 1; while (b > 0) {if ((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static long powl(long a, int b) {if (a == 0) return 0; long ans = 1; while (b > 0) {if ((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static int fli(double d) {return (int) d;}
    static int cei(double d) {return (int) ceil(d);}
    static long fll(double d) {return (long) d;}
    static long cel(double d) {return (long) ceil(d);}
    static int gcf(int a, int b) {return b == 0 ? a : gcf(b, a % b);}
    static long gcf(long a, long b) {return b == 0 ? a : gcf(b, a % b);}
    static int lcm(int a, int b) {return a * b / gcf(a, b);}
    static long lcm(long a, long b) {return a * b / gcf(a, b);}
    static int randInt(int min, int max) {return __rand.nextInt(max - min + 1) + min;}
    static long mix(long x) {x += 0x9e3779b97f4a7c15L; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9L; x = (x ^ (x >> 27)) * 0x94d049bb133111ebL; return x ^ (x >> 31);}
    // array util
    static void reverse(int[] a) {for (int i = 0, n = a.length, half = n / 2; i < half; ++i) {int swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void reverse(long[] a) {for (int i = 0, n = a.length, half = n / 2; i < half; ++i) {long swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void reverse(double[] a) {for (int i = 0, n = a.length, half = n / 2; i < half; ++i) {double swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void reverse(char[] a) {for (int i = 0, n = a.length, half = n / 2; i < half; ++i) {char swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void shuffle(int[] a) {int n = a.length - 1; for (int i = 0; i < n; ++i) {int ind = randInt(i, n); int swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(long[] a) {int n = a.length - 1; for (int i = 0; i < n; ++i) {int ind = randInt(i, n); long swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(double[] a) {int n = a.length - 1; for (int i = 0; i < n; ++i) {int ind = randInt(i, n); double swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void rsort(int[] a) {shuffle(a); sort(a);}
    static void rsort(long[] a) {shuffle(a); sort(a);}
    static void rsort(double[] a) {shuffle(a); sort(a);}
    static int[] copy(int[] a) {int[] ans = new int[a.length]; for (int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    static long[] copy(long[] a) {long[] ans = new long[a.length]; for (int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    static double[] copy(double[] a) {double[] ans = new double[a.length]; for (int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    static char[] copy(char[] a) {char[] ans = new char[a.length]; for (int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    // input
    static void r() throws IOException {input = new StringTokenizer(rline());}
    static int ri() throws IOException {return Integer.parseInt(rline());}
    static long rl() throws IOException {return Long.parseLong(rline());}
    static double rd() throws IOException {return Double.parseDouble(rline());}
    static int[] ria(int n) throws IOException {int[] a = new int[n]; r(); for (int i = 0; i < n; ++i) a[i] = ni(); return a;}
    static int[] riam1(int n) throws IOException {int[] a = new int[n]; r(); for (int i = 0; i < n; ++i) a[i] = ni() - 1; return a;}
    static long[] rla(int n) throws IOException {long[] a = new long[n]; r(); for (int i = 0; i < n; ++i) a[i] = nl(); return a;}
    static double[] rda(int n) throws IOException {double[] a = new double[n]; r(); for (int i = 0; i < n; ++i) a[i] = nd(); return a;}
    static char[] rcha() throws IOException {return rline().toCharArray();}
    static String rline() throws IOException {return __in.readLine();}
    static String n() {return input.nextToken();}
    static int rni() throws IOException {r(); return ni();}
    static int ni() {return Integer.parseInt(n());}
    static long rnl() throws IOException {r(); return nl();}
    static long nl() {return Long.parseLong(n());}
    static double rnd() throws IOException {r(); return nd();}
    static double nd() {return Double.parseDouble(n());}
    // output
    static void pr(int i) {__out.print(i);}
    static void prln(int i) {__out.println(i);}
    static void pr(long l) {__out.print(l);}
    static void prln(long l) {__out.println(l);}
    static void pr(double d) {__out.print(d);}
    static void prln(double d) {__out.println(d);}
    static void pr(char c) {__out.print(c);}
    static void prln(char c) {__out.println(c);}
    static void pr(char[] s) {__out.print(new String(s));}
    static void prln(char[] s) {__out.println(new String(s));}
    static void pr(String s) {__out.print(s);}
    static void prln(String s) {__out.println(s);}
    static void pr(Object o) {__out.print(o);}
    static void prln(Object o) {__out.println(o);}
    static void prln() {__out.println();}
    static void pryes() {prln("yes");}
    static void pry() {prln("Yes");}
    static void prY() {prln("YES");}
    static void prno() {prln("no");}
    static void prn() {prln("No");}
    static void prN() {prln("NO");}
    static boolean pryesno(boolean b) {prln(b ? "yes" : "no"); return b;};
    static boolean pryn(boolean b) {prln(b ? "Yes" : "No"); return b;}
    static boolean prYN(boolean b) {prln(b ? "YES" : "NO"); return b;}
    static void prln(int... a) {for (int i = 0, len = a.length - 1; i < len; pr(a[i]), pr(' '), ++i); if (a.length > 0) prln(a[a.length - 1]); else prln();}
    static void prln(long... a) {for (int i = 0, len = a.length - 1; i < len; pr(a[i]), pr(' '), ++i); if (a.length > 0) prln(a[a.length - 1]); else prln();}
    static void prln(double... a) {for (int i = 0, len = a.length - 1; i < len; pr(a[i]), pr(' '), ++i); if (a.length > 0) prln(a[a.length - 1]); else prln();}
    static <T> void prln(Collection<T> c) {int n = c.size() - 1; Iterator<T> iter = c.iterator(); for (int i = 0; i < n; pr(iter.next()), pr(' '), ++i); if (n >= 0) prln(iter.next()); else prln();}
    static void h() {prln("hlfd"); flush();}
    static void flush() {__out.flush();}
    static void close() {__out.close();}
}

import java.util.*;
import java.io.*;

public class D60 {
    public static void main(String[] args) throws Exception {
        MyScanner sc = new MyScanner();
        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
        long n = sc.nextLong(); dimension = sc.nextInt();
        memo = new long[maxPow][dimension][dimension];
        long [][] matrix = new long[dimension][dimension];
        for (int i = 0; i < matrix.length; i++) {
            if (i != matrix.length - 1) {
                matrix[i][i + 1] = 1;
            } else {
                matrix[i][0] = 1; matrix[i][i] = 1;
            }
        }
        powers(matrix);
        long [][] ret = exp(matrix, n - dimension + 1);
        long [] vector = new long[dimension];
        Arrays.fill(vector, 1);
        long [] ans = transform(vector, ret);
        out.println(n <= dimension - 1 ? 1 : ans[dimension - 1]);
        out.close();
    }

    static long mod = (long) 1e9 + 7; static long [][][] memo; static int maxPow = 63; static int dimension;

    static long [][] multiply(long [][] a, long [][] b) throws Exception {
        if (a[0].length != b.length) {
            throw new Exception("Matrices are not compatible.");
        }
        long [][] ret = new long[a.length][b[0].length];
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < b[0].length; j++) {
                long product = 0;
                for (int k = 0; k < a.length; k++) {
                    product = (product + (a[i][k] * b[k][j]) % mod) % mod;
                }
                ret[i][j] = product;
            }
        }
        return ret;
    }

    static long[][] exp(long [][] a, long pow) throws Exception {
        long [][] ret = getIdentity(dimension);
        for (int i = 0; i < maxPow; i++) {
            if (((pow) & (1L << i)) >> i == 1) {
                ret = multiply(ret, memo[i]);
            }
        }
        return ret;
    }

    static void powers(long [][] a) throws Exception {
        for (int i = 0; i < maxPow; i++) {
            memo[i] = a;
            a = square(a);
        }
    }

    static long [][] square(long [][] a) throws Exception {
        return multiply(a, a);
    }

    static long [][] getIdentity(int dimension) {
        long [][] I = new long[dimension][dimension];
        for (int i = 0; i < dimension; i++) {
            I[i][i] = 1;
        }
        return I;
    }

    static long[] transform(long [] vector, long [][] matrix) throws Exception {
        if (vector.length != matrix[0].length) {
            throw new Exception("Dimensions are not compatible.");
        }
        long [] res = new long[vector.length];
        for (int i = 0; i < vector.length; i++) {
            long sum = 0;
            for (int j = 0; j < vector.length; j++) {
                sum = (sum + (matrix[i][j] * vector[j]) % mod) % mod;
            }
            res[i] = sum;
        }
        return res;
    }

    //-----------MyScanner class for faster input----------
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;

        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }

}

import java.io.*;
import java.util.*;
public class  Main{
	static int mod=(int)1e9+7;
	/*
	 * 3. Matrix Multiplication
	 */
	static int[][] matMul(int[][] A, int[][] B, int p, int q, int r)	//C(p x r) = A(p x q) x (q x r) -- O(p x q x r)
	{
		int[][] C = new int[p][r];
		for(int i = 0; i < p; ++i)
			for(int j = 0; j < r; ++j)
				for(int k = 0; k < q; ++k)
					C[i][j] += (A[i][k] * B[k][j])%mod;
		return C;
	}

	/*
	 * 4. Square Matrix Exponentiation
	 */
	static int[][] matPow(int[][] base, long p)
	{
		int n = base.length;
		int[][] ans = new int[n][n];
		for(int i = 0; i < n; i++)
			ans[i][i] = 1;
		while(p != 0)
		{
			if((p & 1) == 1)
				ans = matMul(ans, base, n, n, n);
			base = matMul(base, base, n, n, n);
			p >>= 1;
		}

		return ans;
	}
	public static void main(String[] args) throws Exception{
		MScanner sc=new MScanner(System.in);
		PrintWriter pw=new PrintWriter(System.out);
		long n=sc.nextLong();
		int m=sc.nextInt();
		int[][]base=new int[m][1];
		for(int i=0;i<m-1;i++)base[i][0]=1;
		base[m-1][0]=2;
		int[][]t=new int[m][m];
		for(int i=0;i<m-1;i++) {
			t[i][i+1]=1;
		}
		t[m-1][0]=1;
		t[m-1][m-1]=1;
		t=matPow(t, n-1);
		int[][]res=matMul(t, base, m, m, 1);
		pw.println(res[0][0]);
		pw.flush();
	}
	static class MScanner {
		StringTokenizer st;
		BufferedReader br;
		public MScanner(InputStream system) {
			br = new BufferedReader(new InputStreamReader(system));
		}

		public MScanner(String file) throws Exception {
			br = new BufferedReader(new FileReader(file));
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}
		public int[] takearr(int n) throws IOException {
	        int[]in=new int[n];for(int i=0;i<n;i++)in[i]=nextInt();
	        return in;
		}
		public long[] takearrl(int n) throws IOException {
	        long[]in=new long[n];for(int i=0;i<n;i++)in[i]=nextLong();
	        return in;
		}
		public Integer[] takearrobj(int n) throws IOException {
	        Integer[]in=new Integer[n];for(int i=0;i<n;i++)in[i]=nextInt();
	        return in;
		}
		public Long[] takearrlobj(int n) throws IOException {
	        Long[]in=new Long[n];for(int i=0;i<n;i++)in[i]=nextLong();
	        return in;
		}
		public String nextLine() throws IOException {
			return br.readLine();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		public double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}

		public char nextChar() throws IOException {
			return next().charAt(0);
		}

		public Long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public boolean ready() throws IOException {
			return br.ready();
		}

		public void waitForInput() throws InterruptedException {
			Thread.sleep(3000);
		}
	}
}

import java.util.*;
import java.io.*;

public class D60 {
    public static void main(String[] args) throws Exception {
        MyScanner sc = new MyScanner();
        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
        long n = sc.nextLong(); dimension = sc.nextInt();
        memo = new long[maxPow][dimension][dimension];
        long [][] matrix = new long[dimension][dimension];
        for (int i = 0; i < matrix.length; i++) {
            if (i != matrix.length - 1) {
                matrix[i][i + 1] = 1;
            } else {
                matrix[i][0] = 1; matrix[i][i] = 1;
            }
        }
        powers(matrix);
        long [][] ret = exp(matrix, n - dimension + 1);
        long [] vector = new long[dimension];
        Arrays.fill(vector, 1);
        long [] ans = transform(vector, ret);
        out.println(ans[dimension - 1]);
        out.close();
    }

    static long mod = (long) 1e9 + 7; static long [][][] memo; static int maxPow = 63; static int dimension;

    static long [][] multiply(long [][] a, long [][] b) throws Exception {
        if (a[0].length != b.length) {
            throw new Exception("Matrices are not compatible.");
        }
        long [][] ret = new long[a.length][b[0].length];
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < b[0].length; j++) {
                long product = 0;
                for (int k = 0; k < a.length; k++) {
                    product = (product + (a[i][k] * b[k][j]) % mod) % mod;
                }
                ret[i][j] = product;
            }
        }
        return ret;
    }

    static long[][] exp(long [][] a, long pow) throws Exception {
        long [][] ret = getIdentity(dimension);
        for (int i = 0; i < maxPow; i++) {
            if (((pow) & (1L << i)) >> i == 1) {
                ret = multiply(ret, memo[i]);
            }
        }
        return ret;
    }

    static void powers(long [][] a) throws Exception {
        for (int i = 0; i < maxPow; i++) {
            memo[i] = a;
            a = square(a);
        }
    }

    static long [][] square(long [][] a) throws Exception {
        return multiply(a, a);
    }

    static long [][] getIdentity(int dimension) {
        long [][] I = new long[dimension][dimension];
        for (int i = 0; i < dimension; i++) {
            I[i][i] = 1;
        }
        return I;
    }

    static long[] transform(long [] vector, long [][] matrix) throws Exception {
        if (vector.length != matrix[0].length) {
            throw new Exception("Dimensions are not compatible.");
        }
        long [] res = new long[vector.length];
        for (int i = 0; i < vector.length; i++) {
            long sum = 0;
            for (int j = 0; j < vector.length; j++) {
                sum = (sum + (matrix[i][j] * vector[j]) % mod) % mod;
            }
            res[i] = sum;
        }
        return res;
    }

    //-----------MyScanner class for faster input----------
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;

        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }

}

import java.util.*;
import java.io.*;

public class D60 {
    public static void main(String[] args) throws Exception {
        MyScanner sc = new MyScanner();
        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
        long n = sc.nextLong(); dimension = sc.nextInt();
        memo = new long[maxPow][dimension][dimension];
        long [][] matrix = new long[dimension][dimension];
        for (int i = 0; i < matrix.length; i++) {
            if (i != matrix.length - 1) {
                matrix[i][i + 1] = 1;
            } else {
                matrix[i][0] = 1; matrix[i][i] = 1;
            }
        }
        powers(matrix);
        long [][] ret = exp(matrix, n - dimension + 1);
        long [] vector = new long[dimension];
        Arrays.fill(vector, 1);
        long [] ans = transform(vector, ret);
        out.println(ans[dimension - 1]);
        out.close();
    }

    static long mod = (long) 1e9 + 7; static long [][][] memo; static int maxPow = 60; static int dimension;

    static long [][] multiply(long [][] a, long [][] b) throws Exception {
        if (a[0].length != b.length) {
            throw new Exception("Matrices are not compatible.");
        }
        long [][] ret = new long[a.length][b[0].length];
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < b[0].length; j++) {
                long product = 0;
                for (int k = 0; k < a.length; k++) {
                    product = (product + a[i][k] * b[k][j]) % mod;
                }
                ret[i][j] = product;
            }
        }
        return ret;
    }

    static long[][] exp(long [][] a, long pow) throws Exception {
        long [][] ret = getIdentity(dimension);
        for (int i = 0; i < maxPow; i++) {
            if (((pow) & (1 << i)) >> i == 1) {
                ret = multiply(ret, memo[i]);
            }
        }
        return ret;
    }

    static void powers(long [][] a) throws Exception {
        for (int i = 0; i < maxPow; i++) {
            memo[i] = a;
            a = square(a);
        }
    }

    static long [][] square(long [][] a) throws Exception {
        return multiply(a, a);
    }

    static long [][] getIdentity(int dimension) {
        long [][] I = new long[dimension][dimension];
        for (int i = 0; i < dimension; i++) {
            I[i][i] = 1;
        }
        return I;
    }

    static long[] transform(long [] vector, long [][] matrix) throws Exception {
        if (vector.length != matrix[0].length) {
            throw new Exception("Dimensions are not compatible.");
        }
        long [] res = new long[vector.length];
        for (int i = 0; i < vector.length; i++) {
            long sum = 0;
            for (int j = 0; j < vector.length; j++) {
                sum = (sum + matrix[i][j] * vector[j]) % mod;
            }
            res[i] = sum;
        }
        return res;
    }

    //-----------MyScanner class for faster input----------
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;

        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }

}

// package Practice.CF1117;

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class CF1117D {
    static FastReader s;
    static PrintWriter out;
    static String INPUT = "1000000000000000000 3\n";
    static int mod = 1000_000_007;
    static long[][] I;

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
        out = new PrintWriter(System.out);
        s = new FastReader(oj);
        long n = s.nextLong();
        int m = s.nextInt();
        long[][] arr = new long[m][m];
        I = new long[m][m];
        arr[m - 1][0] = 1L;
        arr[m - 1][m - 1] = 1L;
        for (int i = 0; i < m - 1; i++) {
            arr[i][i + 1] = 1L;
            I[i][i] = 1L;
        }
        I[m - 1][m - 1] = 1L;
        long[][] fArr = new long[m][1];
        for (int i = 0; i < m; i++) {
            fArr[i][0] = 1L;
        }

        long[][] ans = mult(exp(arr, n - m + 1), fArr);
        out.println(ans[ans.length - 1][ans[0].length - 1] % mod);

//        out.println((ans.add(BigInteger.ONE)).mod(BigInteger.valueOf(mod)));
        if (!oj) {
            System.out.println(Arrays.deepToString(new Object[]{System.currentTimeMillis() - time + " ms"}));
        }
        out.flush();
    }

    public static long[][] exp(long[][] M, long n)
    {
        if (n == 0) return I;
        if (n == 1) return M;
        long[][] res = exp(M, n/2);
        res = mult(res, res);
        if (n %2 == 0) return res;
        return mult(res, M);
    }

    public static long[][] mult(long[][] p, long[][] q) {
        long[][] r = new long[p.length][q[0].length];
        for (int i = 0; i < p.length; i++)
            for (int j = 0; j < q[0].length; j++)
                for (int k = 0; k < q.length; k++) {
                    r[i][j] += p[i][k]*q[k][j];
                    r[i][j] %= mod;
                }
        return r;
    }

    private static class Maths {
        static ArrayList<Long> printDivisors(long n) {
            // Note that this loop runs till square root
            ArrayList<Long> list = new ArrayList<>();
            for (long i = 1; i <= Math.sqrt(n); i++) {
                if (n % i == 0) {
                    if (n / i == i) {
                        list.add(i);
                    } else {
                        list.add(i);
                        list.add(n / i);
                    }
                }
            }
            return list;
        }

        //    GCD - Using Euclid theorem.
        private static long gcd(long a, long b) {
            if (b == 0) {
                return a;
            }

            return gcd(b, a % b);
        }

        //    Extended euclidean algorithm
//    Used to solve equations of the form ax + by = gcd(a,b)
//    return array [d, a, b] such that d = gcd(p, q), ap + bq = d
        static long[] extendedEuclidean(long p, long q) {
            if (q == 0)
                return new long[]{p, 1, 0};

            long[] vals = extendedEuclidean(q, p % q);
            long d = vals[0];
            long a = vals[2];
            long b = vals[1] - (p / q) * vals[2];
            return new long[]{d, a, b};
        }

        // X ^ y mod p
        static long power(long x, long y, long p) {
            long res = 1;
            x = x % p;

            while (y > 0) {
                if ((y & 1) == 1)
                    res = (res * x) % p;
                y = y >> 1;
                x = (x * x) % p;
            }
            return res;
        }

        // Returns modulo inverse of a
        // with respect to m using extended
        // Euclid Algorithm. Refer below post for details:
        // https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/
        static long inv(long a, long m) {
            long m0 = m, t, q;
            long x0 = 0, x1 = 1;

            if (m == 1)
                return 0;

            // Apply extended Euclid Algorithm
            while (a > 1) {
                q = a / m;
                t = m;
                m = a % m;
                a = t;
                t = x0;
                x0 = x1 - q * x0;
                x1 = t;
            }

            // Make x1 positive
            if (x1 < 0)
                x1 += m0;

            return x1;
        }

        // k is size of num[] and rem[].
        // Returns the smallest number
        // x such that:
        // x % num[0] = rem[0],
        // x % num[1] = rem[1],
        // ..................
        // x % num[k-2] = rem[k-1]
        // Assumption: Numbers in num[] are pairwise
        // coprime (gcd for every pair is 1)
        static long findMinX(long num[], long rem[], long k) {
            int prod = 1;
            for (int i = 0; i < k; i++)
                prod *= num[i];

            int result = 0;
            for (int i = 0; i < k; i++) {
                long pp = prod / num[i];
                result += rem[i] * inv(pp, num[i]) * pp;
            }

            return result % prod;
        }
    }

    private static class BS {
        //  Binary search
        private static int binarySearch(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    return mid;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return -1;
        }

        //    First occurence using binary search
        private static int binarySearchFirstOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    high = mid - 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }

        //    Last occurenece using binary search
        private static int binarySearchLastOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    low = mid + 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }
    }

    private static class arrays {
        // Merge sort
        static void merge(int arr[], int l, int m, int r) {
            int n1 = m - l + 1;
            int n2 = r - m;
            int L[] = new int[n1];
            int R[] = new int[n2];
            for (int i = 0; i < n1; ++i)
                L[i] = arr[l + i];
            for (int j = 0; j < n2; ++j)
                R[j] = arr[m + 1 + j];
            int i = 0, j = 0;
            int k = l;
            while (i < n1 && j < n2) {
                if (L[i] <= R[j]) {
                    arr[k] = L[i];
                    i++;
                } else {
                    arr[k] = R[j];
                    j++;
                }
                k++;
            }

            while (i < n1) {
                arr[k] = L[i];
                i++;
                k++;
            }

            while (j < n2) {
                arr[k] = R[j];
                j++;
                k++;
            }
        }

        static void sort(int arr[], int l, int r) {
            if (l < r) {
                int m = (l + r) / 2;
                sort(arr, l, m);
                sort(arr, m + 1, r);
                merge(arr, l, m, r);
            }
        }

        static void sort(int[] arr) {
            sort(arr, 0, arr.length - 1);
        }
    }

    private static class UnionFindDisjointSet {
        int[] parent;
        int[] size;
        int n;
        int size1;

        public UnionFindDisjointSet(int n) {
            this.n = n;
            this.parent = new int[n];
            this.size = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }

            for (int i = 0; i < n; i++) {
                size[i] = 1;
            }

            this.size1 = n;
        }

        private int numDisjointSets() {
            System.out.println(size1);
            return size1;
        }

        private boolean find(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return true;
            }
            return false;
        }

        private int root(int b) {
            while (parent[b] != b) {
                parent[b] = parent[parent[b]];
                b = parent[b];
            }
            return b;
        }

        private void union(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return;
            }

            if (size[rootA] < size[rootB]) {
                parent[rootA] = parent[rootB];
                size[rootB] += size[rootA];
            } else {
                parent[rootB] = parent[rootA];
                size[rootA] += size[rootB];
            }
            size1--;
            System.out.println(Arrays.toString(parent));
        }
    }

    private static class SegTree {
        int[] st;
        int[] arr;

        public SegTree(int[] arr) {
            this.arr = arr;
            int size = (int) Math.ceil(Math.log(arr.length) / Math.log(2));
            st = new int[(int) ((2 * Math.pow(2, size)) - 1)];
            buildSegmentTree(1, 0, arr.length - 1);
        }

        //**********JUST CALL THE CONSTRUCTOR, THIS FUNCTION WILL BE CALLED AUTOMATICALLY******
        private void buildSegmentTree(int index, int L, int R) {
            if (L == R) {
                st[index] = arr[L];
                return;
            }

            buildSegmentTree(index * 2, L, (L + R) / 2);
            buildSegmentTree(index * 2 + 1, (L + R) / 2 + 1, R);
//          Replace this line if you want to change the function of the Segment tree.
            st[index] = Math.min(st[index * 2], st[index * 2 + 1]);
        }

        //***********We have to use this function **************
        private int Query(int queL, int queR) {
            return Query1(1, 0, arr.length - 1, queL, queR);
        }

        //This is a helper function.
        //************* DO NOT USE THIS ****************
        private int Query1(int index, int segL, int segR, int queL, int queR) {
            if (queL > segR || queR < segL) {
                return -1;
            }

            if (queL <= segL && queR >= segR) {
                return st[index];
            }

            int ans1 = Query1(index * 2, segL, (segL + segR) / 2, queL, queR);
            int ans2 = Query1(index * 2 + 1, (segL + segR) / 2 + 1, segR, queL, queR);
            if (ans1 == -1) {
                return ans2;
            }

            if (ans2 == -1) {
                return ans1;
            }
//             Segment tree implemented for range minimum query. Change the below line to change the function.
            return Math.min(ans1, ans2);
        }

        private void update(int idx, int val) {
            update1(1, 0, arr.length - 1, idx, val);
        }

        private void update1(int node, int queL, int queR, int idx, int val) {
            // idx - index to be updated in the array
            // node - index to be updated in the seg tree
            if (queL == queR) {
                // Leaf node
                arr[idx] += val;
                st[node] += val;
            } else {
                int mid = (queL + queR) / 2;
                if (queL <= idx && idx <= mid) {
                    // If idx is in the left child, recurse on the left child
                    update1(2 * node, queL, mid, idx, val);
                } else {
                    // if idx is in the right child, recurse on the right child
                    update1(2 * node + 1, mid + 1, queR, idx, val);
                }
                // Internal node will have the min of both of its children
                st[node] = Math.min(st[2 * node], st[2 * node + 1]);
            }
        }

    }

    private static class FastReader {
        InputStream is;

        public FastReader(boolean onlineJudge) {
            is = onlineJudge ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        }

        byte[] inbuf = new byte[1024];
        public int lenbuf = 0, ptrbuf = 0;

        int readByte() {
            if (lenbuf == -1)
                throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0)
                    return -1;
            }
            return inbuf[ptrbuf++];
        }

        boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b))
                ;
            return b;
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        char nextChar() {
            return (char) skip();
        }

        String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        String nextLine() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while ((!isSpaceChar(b) || b == ' ')) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        char[][] nextMatrix(int n, int m) {
            char[][] map = new char[n][];
            for (int i = 0; i < n; i++)
                map[i] = next(m);
            return map;
        }

        int[] nextIntArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        long[] nextLongArray(int n) {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
                a[i] = nextLong();
            return a;
        }

        int[][] next2DInt(int n, int m) {
            int[][] arr = new int[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextIntArray(m);
            }
            return arr;
        }

        long[][] next2DLong(int n, int m) {
            long[][] arr = new long[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLongArray(m);
            }
            return arr;
        }

        int[] shuffle(int[] arr) {
            Random r = new Random();
            for (int i = 1, j; i < arr.length; i++) {
                j = r.nextInt(i);
                arr[i] = arr[i] ^ arr[j];
                arr[j] = arr[i] ^ arr[j];
                arr[i] = arr[i] ^ arr[j];
            }
            return arr;
        }

        int[] uniq(int[] arr) {
            Arrays.sort(arr);
            int[] rv = new int[arr.length];
            int pos = 0;
            rv[pos++] = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if (arr[i] != arr[i - 1]) {
                    rv[pos++] = arr[i];
                }
            }
            return Arrays.copyOf(rv, pos);
        }
    }

}

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.*;
import java.util.*;
import java.util.LinkedList;
import java.math.*;
import java.lang.*;
import java.util.PriorityQueue;
import static java.lang.Math.*;
@SuppressWarnings("unchecked")
public class Solution implements Runnable {
    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private SpaceCharFilter filter;
        private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars==-1)
                throw new InputMismatchException();

            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                }
                catch (IOException e) {
                    throw new InputMismatchException();
                }

                if(numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
        public int nextInt() {
            int c = read();

            while(isSpaceChar(c))
                c = read();

            int sgn = 1;

            if (c == '-') {
                sgn = -1;
                c = read();
            }

            int res = 0;
            do {
                if(c<'0'||c>'9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            while (!isSpaceChar(c));

            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;

            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            while (!isSpaceChar(c));
                return res * sgn;
        }

        public double nextDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, nextInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, nextInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }

        public String readString() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            }
            while (!isSpaceChar(c));

            return res.toString();
        }

        public boolean isSpaceChar(int c) {
            if (filter != null)
                return filter.isSpaceChar(c);
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public String next() {
            return readString();
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);
        }
    }
    public static long min(long a,long b)
    {
        if(a>b)
        {
            return b;
        }
        return a;
    }
    public static int min(int a,int b)
    {
        if(a>b)
        {
            return b;
        }
        return a;
    }
    public static long max(long a,long b)
    {
        if(a>b)
        {
            return a;
        }
        return b;
    }
    public static int max(int a,int b)
    {
        if(a>b)
        {
            return a;
        }
        return b;
    }
    static class pair
    {
      long x;
      long y;
      pair(long x,long y)
      {
        this.x = x;
        this.y = y;
      }
    }
    public static int gcd(int a,int b)
    {
        if(a==0)
        return b;
        if(b==0)
        return a;
        while((a%=b)!=0&&(b%=a)!=0);
        return a^b;
    }
    public static long mod(long x)
    {
      if(x>0)
      {
        return x;
      }
      return -x;
    }
    static int mod = (int)1e9+7;
    static long[][] dp;
    static long[][] mat;
    static int k;
    public static long[][] mult(long[][] a,long[][] b)
    {
      int n = a.length;
      int m = b[0].length;
      long[][] res = new long[n][m];
      for(int i=0;i<n;i++)
      {
        for(int j=0;j<m;j++)
        {
          for(int k=0;k<a[0].length;k++)
          {
            res[i][j]  = (res[i][j]+a[i][k]*b[k][j])%mod;
          }
        }
      }
      return res;
    }
    public static long[][] expo(long[][] mat,long pow)
    {
      long[][] res = new long[mat.length][mat.length];
      for(int i=0;i<res.length;i++)
      {
        res[i][i] = 1;
      }
      while(pow!=0)
      {
        if((pow&1)==1)
        {
          res = mult(res,mat);
        }
        mat = mult(mat,mat);
        pow = pow>>1;
      }
      return res;
    }
    public static int random(int min,int max)
    {
      return min+(int)((max-min)*Math.random());
    }
    public static void main(String args[]) throws Exception {
        new Thread(null, new Solution(),"Main",1<<26).start();
    }    public void run() {
      InputReader sc  = new InputReader(System.in);
      PrintWriter out = new PrintWriter(System.out);
      int t1 = 1;
      while(t1-->0)
      {
        long n = sc.nextLong();
        k = sc.nextInt();
        dp = new long[k][1];
        for(int i=0;i<k;i++)
        {
          dp[i][0] = 1;
        }
        dp[k-1][0] = 2;
        mat = new long[k][k];
        for(int i=0;i<k-1;i++)
        {
          for(int j=1;j<k;j++)
          {
            mat[i][j] = 1;
          }
        }
        mat[k-1][0] = 1;
        mat[k-1][k-1] = 1;
        mat = expo(mat,n-k);
        dp = mult(mat,dp);
        out.println(dp[k-1][0]%mod);
      }
      out.close();
  }
}

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.*;
import java.util.*;
import java.util.LinkedList;
import java.math.*;
import java.lang.*;
import java.util.PriorityQueue;
import static java.lang.Math.*;
@SuppressWarnings("unchecked")
public class Solution implements Runnable {
    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private SpaceCharFilter filter;
        private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars==-1)
                throw new InputMismatchException();

            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                }
                catch (IOException e) {
                    throw new InputMismatchException();
                }

                if(numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
        public int nextInt() {
            int c = read();

            while(isSpaceChar(c))
                c = read();

            int sgn = 1;

            if (c == '-') {
                sgn = -1;
                c = read();
            }

            int res = 0;
            do {
                if(c<'0'||c>'9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            while (!isSpaceChar(c));

            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;

            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            while (!isSpaceChar(c));
                return res * sgn;
        }

        public double nextDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, nextInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, nextInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }

        public String readString() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            }
            while (!isSpaceChar(c));

            return res.toString();
        }

        public boolean isSpaceChar(int c) {
            if (filter != null)
                return filter.isSpaceChar(c);
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public String next() {
            return readString();
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);
        }
    }
    public static long min(long a,long b)
    {
        if(a>b)
        {
            return b;
        }
        return a;
    }
    public static int min(int a,int b)
    {
        if(a>b)
        {
            return b;
        }
        return a;
    }
    public static long max(long a,long b)
    {
        if(a>b)
        {
            return a;
        }
        return b;
    }
    public static int max(int a,int b)
    {
        if(a>b)
        {
            return a;
        }
        return b;
    }
    static class pair
    {
      long x;
      long y;
      pair(long x,long y)
      {
        this.x = x;
        this.y = y;
      }
    }
    public static int gcd(int a,int b)
    {
        if(a==0)
        return b;
        if(b==0)
        return a;
        while((a%=b)!=0&&(b%=a)!=0);
        return a^b;
    }
    public static long mod(long x)
    {
      if(x>0)
      {
        return x;
      }
      return -x;
    }
    static int mod = (int)1e9+7;
    static long[][] dp;
    static long[][] mat;
    static int k;
    public static long[][] mult(long[][] a,long[][] b)
    {
      int n = a.length;
      int m = b[0].length;
      long[][] res = new long[n][m];
      for(int i=0;i<n;i++)
      {
        for(int j=0;j<m;j++)
        {
          for(int k=0;k<a[0].length;k++)
          {
            res[i][j]  = (res[i][j]+a[i][k]*b[k][j])%mod;
          }
        }
      }
      return res;
    }
    public static long[][] expo(long[][] mat,long pow)
    {
      long[][] res = new long[mat.length][mat.length];
      for(int i=0;i<res.length;i++)
      {
        res[i][i] = 1;
      }
      while(pow!=0)
      {
        if((pow&1)==1)
        {
          res = mult(res,mat);
        }
        mat = mult(mat,mat);
        pow = pow>>1;
      }
      return res;
    }
    public static int random(int min,int max)
    {
      return min+(int)((max-min)*Math.random());
    }
    public static void main(String args[]) throws Exception {
        new Thread(null, new Solution(),"Main",1<<26).start();
    }    public void run() {
      InputReader sc  = new InputReader(System.in);
      PrintWriter out = new PrintWriter(System.out);
      int t1 = 1;
      while(t1-->0)
      {
        long n = sc.nextLong();
        k = sc.nextInt();
        dp = new long[k][1];
        for(int i=0;i<k;i++)
        {
          dp[i][0] = 1;
        }
        dp[k-1][0] = 2;
        if(n<=k)
        {
          out.println(dp[(int)(n-1)][0]);
          out.close();
          return;
        }
        mat = new long[k][k];
        for(int i=0;i<k-1;i++)
        {
          for(int j=1;j<k;j++)
          {
            mat[i][j] = 1;
          }
        }
        mat[k-1][0] = 1;
        mat[k-1][k-1] = 1;
        mat = expo(mat,n-k);
        dp = mult(mat,dp);
        out.println(dp[k-1][0]%mod);
      }
      out.close();
  }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author llamaoo7
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DMagicGems solver = new DMagicGems();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems {
        int MAX = 1_000_000_007;

        long add(long a, long b) {
            return (a + b) % MAX;
        }

        long mult(long a, long b) {
            return (a * b) % MAX;
        }

        long[][] base(int m) {
            long[][] M = new long[m][m];
            M[0][0] = 1;
            M[0][m - 1] = 1;
            for (int i = 1; i < m; i++) M[i][i - 1] = 1;
            return M;
        }

        void matMult(long[][] a, long[][] b) {
            int n = a.length;
            long[][] temp = new long[n][n];
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++) {
                    temp[i][j] = 0;
                    for (int k = 0; k < n; k++) temp[i][j] = add(temp[i][j], mult(a[i][k], b[k][j]));
                }
            for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) a[i][j] = temp[i][j];
        }

        void matPow(long[][] f, long n) {
            if (n == 1) return;
            matPow(f, n / 2);
            matMult(f, f);
            if (n % 2 == 1) matMult(f, base(f.length));
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long n = in.nextLong();
            int m = in.nextInt();
            if (m > n) {
                out.println(1);
                return;
            }
            long[][] M = base(m);
            matPow(M, n - m + 1);
            out.println(M[0][0] + M[0][m - 1]);
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}

import java.io.*;
import java.util.Arrays;
import java.util.StringJoiner;
import java.util.StringTokenizer;
import java.util.function.IntBinaryOperator;

public class Main {

    static long N;
    static int M;

    public static void main(String[] args) {
        FastScanner sc = new FastScanner(System.in);
        N = sc.nextLong();
        M = sc.nextInt();

        System.out.println(solve());
    }

    static int MOD = 1_000_000_007;

    static int solve() {
        // 右側に 0* or 1 をくっつけていくDPを考える
        // M=3のケース
        // f4 = f1 + f3
        // f3 = f2
        // f2 = f1
        IntMat mat = new IntMat(M, M);
        mat.set(0, 0, 1);
        mat.set(0, M-1, 1);
        for (int i = 1; i < M; i++) {
            mat.set(i, i-1, 1);
        }

        IntMat powed = IntMat.pow(mat, N, MOD);
        IntMat in = new IntMat(M, 1);
        in.set(0, 0, 1);
        IntMat out = IntMat.dot(powed, in, MOD);
        return out.get(0, 0);
    }

    static class IntMat {

        final int[][] mat;

        IntMat(int r, int c) {
            mat = new int[r][c];
        }

        IntMat(int[][] mat) {
            this.mat = mat;
        }

        IntMat(int[] vec) {
            mat = new int[vec.length][1];
            for (int i = 0; i < vec.length; i++) {
                mat[i][0] = vec[i];
            }
        }

        static IntMat pow(IntMat m, long k, int mod) {
            if( m.row() != m.col() ) throw new IllegalArgumentException("row != col : " + m.row() + " " + m.col());

            int n = m.row();
            IntMat ret = new IntMat(n, n);
            for (int i = 0; i < n; i++) {
                ret.set(i, i, 1);
            }
            if( k == 0 ) return ret; // どうだろ...

            while( k > 0 ) {
                if( (k & 1) == 1 ) {
                    ret = IntMat.dot(ret, m, mod);
                }

                m = IntMat.dot(m, m, mod);
                k = k >> 1L;
            }
            return ret;
        }

        static IntMat pow(IntMat m, long k, IntBinaryOperator mul, IntBinaryOperator add) {
            if( m.row() != m.col() ) throw new IllegalArgumentException("row != col : " + m.row() + " " + m.col());

            int n = m.row();
            IntMat ret = new IntMat(n, n);
            for (int i = 0; i < n; i++) {
                ret.set(i, i, 1);
            }
            if( k == 0 ) return ret; // どうだろ...

            while( k > 0 ) {
                if( (k & 1) == 1 ) {
                    ret = IntMat.dot(ret, m, mul, add);
                }

                m = IntMat.dot(m, m, mul, add);
                k = k >> 1L;
            }
            return ret;
        }

        static IntMat dot(IntMat a, IntMat b) {
            return dot(a, b, (i, j) -> i*j, (i, j) -> i+j);
        }

        static IntMat dot(IntMat a, IntMat b, IntBinaryOperator mul, IntBinaryOperator add) {
            int[][] ret = new int[a.row()][b.col()];

            for (int r = 0; r < a.row(); r++) {
                for (int c = 0; c < b.col(); c++) {
                    int sum = 0;
                    for (int i = 0; i < b.row(); i++) {
                        sum = add.applyAsInt(sum, mul.applyAsInt(a.get(r, i), b.get(i, c)));
                    }
                    ret[r][c] = sum;
                }
            }
            return new IntMat(ret);
        }

        static IntMat dot(IntMat a, IntMat b, int mod) {
            long m2 = (long)mod * mod;

            int[][] ret = new int[a.row()][b.col()];

            for (int r = 0; r < a.row(); r++) {
                for (int c = 0; c < b.col(); c++) {
                    long sum = 0;
                    for (int i = 0; i < b.row(); i++) {
                        long mul = a.mat[r][i] * b.mat[i][c];
                        if( mul >= m2 ) {
                            mul -= m2;
                        }
                        sum += mul;
                    }
                    sum %= mod;
                    ret[r][c] = (int)sum;
                }
            }
            return new IntMat(ret);
        }

        void set(int r, int c, int n) {
            mat[r][c] = n;
        }

        int get(int r, int c) {
            try {
                return mat[r][c];
            } catch( ArrayIndexOutOfBoundsException e ) {
                throw new RuntimeException("wrong index : r=" + r + " c=" + c + " row=" + row() + " col=" + col());
            }
        }

        int row() {
            return mat.length;
        }

        int col() {
            return mat[0].length;
        }
    }

    @SuppressWarnings("unused")
    static class FastScanner {
        private BufferedReader reader;
        private StringTokenizer tokenizer;

        FastScanner(InputStream in) {
            reader = new BufferedReader(new InputStreamReader(in));
            tokenizer = null;
        }

        String next() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        String nextLine() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    return reader.readLine();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken("\n");
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        int[] nextIntArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++) a[i] = nextInt();
            return a;
        }

        int[] nextIntArray(int n, int delta) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++) a[i] = nextInt() + delta;
            return a;
        }

        long[] nextLongArray(int n) {
            long[] a = new long[n];
            for (int i = 0; i < n; i++) a[i] = nextLong();
            return a;
        }
    }

    static void writeLines(int[] as) {
        PrintWriter pw = new PrintWriter(System.out);
        for (int a : as) pw.println(a);
        pw.flush();
    }

    static void writeLines(long[] as) {
        PrintWriter pw = new PrintWriter(System.out);
        for (long a : as) pw.println(a);
        pw.flush();
    }

    static void writeSingleLine(int[] as) {
        PrintWriter pw = new PrintWriter(System.out);
        for (int i = 0; i < as.length; i++) {
            if (i != 0) pw.print(" ");
            pw.print(as[i]);
        }
        pw.println();
        pw.flush();
    }

    static int max(int... as) {
        int max = Integer.MIN_VALUE;
        for (int a : as) max = Math.max(a, max);
        return max;
    }

    static int min(int... as) {
        int min = Integer.MAX_VALUE;
        for (int a : as) min = Math.min(a, min);
        return min;
    }

    static void debug(Object... args) {
        StringJoiner j = new StringJoiner(" ");
        for (Object arg : args) {
            if (arg == null) j.add("null");
            else if (arg instanceof int[]) j.add(Arrays.toString((int[]) arg));
            else if (arg instanceof long[]) j.add(Arrays.toString((long[]) arg));
            else if (arg instanceof double[]) j.add(Arrays.toString((double[]) arg));
            else if (arg instanceof Object[]) j.add(Arrays.toString((Object[]) arg));
            else j.add(arg.toString());
        }
        System.err.println(j.toString());
    }

    static void printSingleLine(int[] array) {
        PrintWriter pw = new PrintWriter(System.out);
        for (int i = 0; i < array.length; i++) {
            if (i != 0) pw.print(" ");
            pw.print(array[i]);
        }
        pw.println();
        pw.flush();
    }

    static int lowerBound(int[] array, int value) {
        int lo = 0, hi = array.length, mid;
        while (lo < hi) {
            mid = (hi + lo) / 2;
            if (array[mid] < value) lo = mid + 1;
            else hi = mid;
        }
        return lo;
    }

    static int upperBound(int[] array, int value) {
        int lo = 0, hi = array.length, mid;
        while (lo < hi) {
            mid = (hi + lo) / 2;
            if (array[mid] <= value) lo = mid + 1;
            else hi = mid;
        }
        return lo;
    }
}

import java.io.*;
import java.util.Arrays;
import java.util.StringJoiner;
import java.util.StringTokenizer;
import java.util.function.IntBinaryOperator;

public class Main {

    static long N;
    static int M;

    public static void main(String[] args) {
        FastScanner sc = new FastScanner(System.in);
        N = sc.nextLong();
        M = sc.nextInt();

        System.out.println(solve());
    }

    static int MOD = 1_000_000_007;

    static int solve() {
        // 右側に 0* or 1 をくっつけていくDPを考える
        // M=3のケース
        // f4 = f1 + f3
        // f3 = f2
        // f2 = f1
        IntMat mat = new IntMat(M, M);
        mat.set(0, 0, 1);
        mat.set(0, M-1, 1);
        for (int i = 1; i < M; i++) {
            mat.set(i, i-1, 1);
        }

        IntMat powed = IntMat.pow(mat, N, MOD);
        IntMat in = new IntMat(M, 1);
        in.set(0, 0, 1);
        IntMat out = IntMat.dot(powed, in, MOD);
        return out.get(0, 0);
    }

    static class IntMat {

        final int[][] mat;

        IntMat(int r, int c) {
            mat = new int[r][c];
        }

        IntMat(int[][] mat) {
            this.mat = mat;
        }

        IntMat(int[] vec) {
            mat = new int[vec.length][1];
            for (int i = 0; i < vec.length; i++) {
                mat[i][0] = vec[i];
            }
        }

        static IntMat pow(IntMat m, long k, int mod) {
            if( m.row() != m.col() ) throw new IllegalArgumentException("row != col : " + m.row() + " " + m.col());

            int n = m.row();
            IntMat ret = new IntMat(n, n);
            for (int i = 0; i < n; i++) {
                ret.set(i, i, 1);
            }
            if( k == 0 ) return ret; // どうだろ...

            while( k > 0 ) {
                if( (k & 1) == 1 ) {
                    ret = IntMat.dot(ret, m, mod);
                }

                m = IntMat.dot(m, m, mod);
                k = k >> 1L;
            }
            return ret;
        }

        static IntMat pow(IntMat m, long k, IntBinaryOperator mul, IntBinaryOperator add) {
            if( m.row() != m.col() ) throw new IllegalArgumentException("row != col : " + m.row() + " " + m.col());

            int n = m.row();
            IntMat ret = new IntMat(n, n);
            for (int i = 0; i < n; i++) {
                ret.set(i, i, 1);
            }
            if( k == 0 ) return ret; // どうだろ...

            while( k > 0 ) {
                if( (k & 1) == 1 ) {
                    ret = IntMat.dot(ret, m, mul, add);
                }

                m = IntMat.dot(m, m, mul, add);
                k = k >> 1L;
            }
            return ret;
        }

        static IntMat dot(IntMat a, IntMat b) {
            return dot(a, b, (i, j) -> i*j, (i, j) -> i+j);
        }

        static IntMat dot(IntMat a, IntMat b, IntBinaryOperator mul, IntBinaryOperator add) {
            int[][] ret = new int[a.row()][b.col()];

            for (int r = 0; r < a.row(); r++) {
                for (int c = 0; c < b.col(); c++) {
                    int sum = 0;
                    for (int i = 0; i < b.row(); i++) {
                        sum = add.applyAsInt(sum, mul.applyAsInt(a.get(r, i), b.get(i, c)));
                    }
                    ret[r][c] = sum;
                }
            }
            return new IntMat(ret);
        }

        static IntMat dot(IntMat a, IntMat b, int mod) {
            long m2 = (long)mod * mod;

            int ar = a.row();
            int bc = b.col();
            int br = b.row();
            int[][] ret = new int[ar][bc];

            for (int r = 0; r < ar; r++) {
                for (int c = 0; c < bc; c++) {
                    long sum = 0;
                    for (int i = 0; i < br; i++) {
                        long ab = (long)a.mat[r][i] * b.mat[i][c];
                        sum += ab;
                        if( sum >= m2 ) {
                            sum -= m2;
                        }
                    }
                    ret[r][c] = (int)sum % mod;
                }
            }
            return new IntMat(ret);
        }

        void set(int r, int c, int n) {
            mat[r][c] = n;
        }

        int get(int r, int c) {
            try {
                return mat[r][c];
            } catch( ArrayIndexOutOfBoundsException e ) {
                throw new RuntimeException("wrong index : r=" + r + " c=" + c + " row=" + row() + " col=" + col());
            }
        }

        int row() {
            return mat.length;
        }

        int col() {
            return mat[0].length;
        }
    }

    @SuppressWarnings("unused")
    static class FastScanner {
        private BufferedReader reader;
        private StringTokenizer tokenizer;

        FastScanner(InputStream in) {
            reader = new BufferedReader(new InputStreamReader(in));
            tokenizer = null;
        }

        String next() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        String nextLine() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    return reader.readLine();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken("\n");
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        int[] nextIntArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++) a[i] = nextInt();
            return a;
        }

        int[] nextIntArray(int n, int delta) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++) a[i] = nextInt() + delta;
            return a;
        }

        long[] nextLongArray(int n) {
            long[] a = new long[n];
            for (int i = 0; i < n; i++) a[i] = nextLong();
            return a;
        }
    }

    static void writeLines(int[] as) {
        PrintWriter pw = new PrintWriter(System.out);
        for (int a : as) pw.println(a);
        pw.flush();
    }

    static void writeLines(long[] as) {
        PrintWriter pw = new PrintWriter(System.out);
        for (long a : as) pw.println(a);
        pw.flush();
    }

    static void writeSingleLine(int[] as) {
        PrintWriter pw = new PrintWriter(System.out);
        for (int i = 0; i < as.length; i++) {
            if (i != 0) pw.print(" ");
            pw.print(as[i]);
        }
        pw.println();
        pw.flush();
    }

    static int max(int... as) {
        int max = Integer.MIN_VALUE;
        for (int a : as) max = Math.max(a, max);
        return max;
    }

    static int min(int... as) {
        int min = Integer.MAX_VALUE;
        for (int a : as) min = Math.min(a, min);
        return min;
    }

    static void debug(Object... args) {
        StringJoiner j = new StringJoiner(" ");
        for (Object arg : args) {
            if (arg == null) j.add("null");
            else if (arg instanceof int[]) j.add(Arrays.toString((int[]) arg));
            else if (arg instanceof long[]) j.add(Arrays.toString((long[]) arg));
            else if (arg instanceof double[]) j.add(Arrays.toString((double[]) arg));
            else if (arg instanceof Object[]) j.add(Arrays.toString((Object[]) arg));
            else j.add(arg.toString());
        }
        System.err.println(j.toString());
    }

    static void printSingleLine(int[] array) {
        PrintWriter pw = new PrintWriter(System.out);
        for (int i = 0; i < array.length; i++) {
            if (i != 0) pw.print(" ");
            pw.print(array[i]);
        }
        pw.println();
        pw.flush();
    }

    static int lowerBound(int[] array, int value) {
        int lo = 0, hi = array.length, mid;
        while (lo < hi) {
            mid = (hi + lo) / 2;
            if (array[mid] < value) lo = mid + 1;
            else hi = mid;
        }
        return lo;
    }

    static int upperBound(int[] array, int value) {
        int lo = 0, hi = array.length, mid;
        while (lo < hi) {
            mid = (hi + lo) / 2;
            if (array[mid] <= value) lo = mid + 1;
            else hi = mid;
        }
        return lo;
    }
}

import java.io.*;
import java.util.*;
import java.util.function.BinaryOperator;

public class Main {
    private final static long mod = 1000000007;

    private final static int MAXN = 1000001;

    private static long power(long x, long y, long m) {
        long temp;
        if (y == 0)
            return 1;
        temp = power(x, y / 2, m);
        temp = (temp * temp) % m;
        if (y % 2 == 0)
            return temp;
        else
            return ((x % m) * temp) % m;
    }

    private static long power(long x, long y) {
        return power(x, y, mod);
    }

    private static long gcd(long a, long b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

    static int nextPowerOf2(int a) {
        return 1 << nextLog2(a);
    }

    static int nextLog2(int a) {
        return (a == 0 ? 0 : 32 - Integer.numberOfLeadingZeros(a - 1));
    }

    private static long modInverse(long a, long m) {
        long m0 = m;
        long y = 0, x = 1;
        if (m == 1)
            return 0;
        while (a > 1) {
            long q = a / m;
            long t = m;
            m = a % m;
            a = t;
            t = y;
            y = x - q * y;
            x = t;
        }
        if (x < 0)
            x += m0;
        return x;
    }

    private static int[] getLogArr(int n) {
        int arr[] = new int[n + 1];
        for (int i = 1; i < n + 1; i++) {
            arr[i] = (int) (Math.log(i) / Math.log(2) + 1e-10);
        }
        return arr;
    }

    private static int log[] = getLogArr(MAXN);

    private static int getLRSpt(int st[][], int L, int R, BinaryOperator<Integer> binaryOperator) {
        int j = log[R - L + 1];
        return binaryOperator.apply(st[L][j], st[R - (1 << j) + 1][j]);
    }

    private static int[][] getSparseTable(int array[], BinaryOperator<Integer> binaryOperator) {
        int k = log[array.length + 1] + 1;
        int st[][] = new int[array.length + 1][k + 1];

        for (int i = 0; i < array.length; i++)
            st[i][0] = array[i];

        for (int j = 1; j <= k; j++) {
            for (int i = 0; i + (1 << j) <= array.length; i++) {
                st[i][j] = binaryOperator.apply(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
            }
        }
        return st;
    }

    static class Subset {
        int parent;
        int rank;

        @Override
        public String toString() {
            return "" + parent;
        }
    }

    static int find(Subset[] Subsets, int i) {
        if (Subsets[i].parent != i)
            Subsets[i].parent = find(Subsets, Subsets[i].parent);
        return Subsets[i].parent;
    }

    static void union(Subset[] Subsets, int x, int y) {
        int xroot = find(Subsets, x);
        int yroot = find(Subsets, y);

        if (Subsets[xroot].rank < Subsets[yroot].rank)
            Subsets[xroot].parent = yroot;
        else if (Subsets[yroot].rank < Subsets[xroot].rank)
            Subsets[yroot].parent = xroot;
        else {
            Subsets[xroot].parent = yroot;
            Subsets[yroot].rank++;
        }
    }

    private static int maxx(Integer... a) {
        return Collections.max(Arrays.asList(a));
    }

    private static int minn(Integer... a) {
        return Collections.min(Arrays.asList(a));
    }

    private static long maxx(Long... a) {
        return Collections.max(Arrays.asList(a));
    }

    private static long minn(Long... a) {
        return Collections.min(Arrays.asList(a));
    }

    private static class Pair<T, U> implements Comparable<Pair<T, U>> {
        T a;
        U b;

        public Pair(T a, U b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pair pair = (Pair) o;
            return a.equals(pair.a) &&
                    b.equals(pair.b);
        }

        @Override
        public int hashCode() {
            return Objects.hash(a, b);
        }

        @Override
        public String toString() {
            return "(" + a +
                    "," + b +
                    ')';
        }

        @Override
        public int compareTo(Pair<T, U> o) {
            return (int) (this.a.equals(o.a) ?
                    this.b.equals(o.b) ? 0 :
                            ((Integer) this.b - (Integer) o.b) / Math.abs((Integer) this.b - (Integer) o.b) :
                    ((Integer) this.a - (Integer) o.a) / Math.abs((Integer) this.a - (Integer) o.a));
        }
    }

    public static int upperBound(List<Integer> list, int value) {
        int low = 0;
        int high = list.size();
        while (low < high) {
            final int mid = (low + high) / 2;
            if (value >= list.get(mid)) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return low;
    }

    private static int[] getLPSArray(String pattern) {
        int i, j, n = pattern.length();
        int[] lps = new int[pattern.length()];
        lps[0] = 0;
        for (i = 1, j = 0; i < n; ) {
            if (pattern.charAt(i) == pattern.charAt(j)) {
                lps[i++] = ++j;
            } else if (j > 0) {
                j = lps[j - 1];
            } else {
                lps[i++] = 0;
            }
        }
        return lps;
    }

    private static List<Integer> findPattern(String text, String pattern) {
        List<Integer> matchedIndexes = new ArrayList<>();
        if (pattern.length() == 0) {
            return matchedIndexes;
        }
        int[] lps = getLPSArray(pattern);
        int i = 0, j = 0, n = text.length(), m = pattern.length();
        while (i < n) {
            if (text.charAt(i) == pattern.charAt(j)) {
                i++;
                j++;
            }
            if (j == m) {
                matchedIndexes.add(i - j);
                j = lps[j - 1];
            }
            if (i < n && text.charAt(i) != pattern.charAt(j)) {
                if (j > 0) {
                    j = lps[j - 1];
                } else {
                    i++;
                }
            }
        }
        return matchedIndexes;
    }

    private static Set<Long> getDivisors(long n) {
        Set<Long> divisors = new HashSet<>();
        divisors.add(1L);
        divisors.add(n);
        for (long i = 2; i <= Math.sqrt(n); i++) {
            if (n % i == 0) {
                divisors.add(i);
                divisors.add(n / i);
            }
        }
        return divisors;
    }

    private static long getLCM(long a, long b) {
        return (Math.max(a, b) / gcd(a, b)) * Math.min(a, b);
    }

    static long fac[] = new long[2000005];
    static long ifac[] = new long[2000005];

    private static void preCompute(int n) {
        fac = new long[n + 1];
        ifac = new long[n + 1];
        fac[0] = ifac[0] = fac[1] = ifac[1] = 1;
        int i;
        for (i = 2; i < n + 1; i++) {
            fac[i] = (i * fac[i - 1]) % mod;
            ifac[i] = (power(i, mod - 2) * ifac[i - 1]) % mod;
        }
    }

    private static long C(int n, int r) {
        if (n < 0 || r < 0) return 1;
        if (r > n) return 1;
        return (fac[n] * ((ifac[r] * ifac[n - r]) % mod)) % mod;
    }

    static long getSum(long BITree[], int index)
    {
        long sum = 0;
        index = index + 1;
        while(index>0)
        {
            index -= index & (-index);
        }
        return sum;
    }

    public static void updateBIT(long BITree[], int index, long val)
    {
        index = index + 1;
        while(index <= BITree.length-1) {
            BITree[index] += val;
            index += index & (-index);
        }
    }
    long[] constructBITree(int arr[], int m)
    {
        int n=arr.length;
        long BITree[] = new long[m+1];
        for(int i=1; i<=n; i++)
            BITree[i] = 0;
        for(int i = 0; i < n; i++)
            updateBIT(BITree, i, arr[i]);
        return BITree;
    }

    private static int upperBound(int a[], int l, int r, int x) {
        if(l>r)return -1;
        if(l==r){
            if(a[l]<=x) {
                return -1;
            }
            else{
                return a[l];
            }
        }
        int m=(l+r)/2;
        if(a[m]<=x) {
            return upperBound(a, m+1,r,x);
        }
        else {
            return upperBound(a, l,m,x);
        }
    }

    private static long getCntOdd(long x, long y)
    {
        long p2 = 1;
        long ans = 0;
        while (p2 * x <= y)
        {
            long hi = Math.min (y, p2 * (x + 1) - 1);
            ans += hi - p2 * x + 1;
            p2 *= 2;
        }
        return ans;
    }

    private static long getCnt(long x, long y)
    {
        long ans=getCntOdd(x,y);
        if(x%2==0) ans+=getCntOdd(x+1,y);
        //System.out.println(ans);
        return ans;
    }

    private static void mul(long A[][], long B[][]){
        int i,j,k,n=A.length;
        long C[][]=new long[n][n];
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                for(k=0;k<n;k++){
                    C[i][j]=(C[i][j]+(A[i][k]*B[k][j])%mod)%mod;
                }
            }
        }
        for(i=0;i<n;i++) {
            for (j = 0; j < n; j++) {
                A[i][j]=C[i][j];
            }
        }
    }

    private static void power(long A[][], long base[][], long n) {
        if(n<2){
            return;
        }
        power(A, base, n/2);
        mul(A,A);
        if(n%2==1){
            mul(A, base);
        }
    }

    public static void main(String[] args) throws Exception {

        long START_TIME = System.currentTimeMillis();
        try (FastReader in = new FastReader();
             FastWriter out = new FastWriter()) {

            int t, i, j,f, k,m, ti, tidx, gm, q, g;
            //for (t = in.nextInt(), tidx = 1; tidx <= t; tidx++)
            {
                long n,w,x, y = 0, z = 0, sum = 0, bhc = 0, ans = 0,l,r;
                //out.print(String.format("Case #%d: ", tidx));
                n=in.nextLong();
                m=in.nextInt();
                long baseMat[][]=new long[m+1][m+1];
                long baseMat1[][]=new long[m+1][m+1];
                baseMat1[0][0]=baseMat1[0][m]=baseMat[0][0]=baseMat[0][m]=1;
                for(i=1,j=0;i<=m;i++,j++){
                    baseMat1[i][j]=baseMat[i][j]=1;
                }
                if(n<m){
                    out.println(1);
                }
                power(baseMat, baseMat1, n);
                out.println((baseMat[0][0]+baseMat[0][m])%mod);

            }
            if (args.length > 0 && "ex_time".equals(args[0])) {
                out.print("\nTime taken: ");
                out.println(System.currentTimeMillis() - START_TIME);
            }
            out.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static class FastReader implements Closeable {
        private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer st;

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        int[] nextIntArr(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextInt();
            }
            return arr;
        }

        int[] nextIntegerArr(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextInt();
            }
            return arr;
        }

        double[] nextDoubleArr(int n) {
            double[] arr = new double[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextDouble();
            }
            return arr;
        }

        long[] nextLongArr(int n) {
            long[] arr = new long[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLong();
            }
            return arr;
        }

        String[] nextStrArr(int n) {
            String[] arr = new String[n];
            for (int i = 0; i < n; i++) {
                arr[i] = next();
            }
            return arr;
        }

        long[][] nextLongArr2(int n, int m) {
            long[][] arr = new long[n][m];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLongArr(m);
            }
            return arr;
        }

        @Override
        public void close() throws IOException {
            br.close();
        }
    }

    public static class FastWriter implements Closeable {
        BufferedWriter bw;
        StringBuilder sb = new StringBuilder();
        List<String> list = new ArrayList<>();
        Set<String> set = new HashSet<>();

        public FastWriter() {
            bw = new BufferedWriter(new OutputStreamWriter(System.out));
        }

        <T> void commit() throws IOException {
            bw.write(sb.toString());
            bw.flush();
            sb = new StringBuilder();
        }

        public <T> void print(T obj) throws IOException {
            sb.append(obj.toString());
        }

        public void println() throws IOException {
            print("\n");
        }

        public <T> void println(T obj) throws IOException {
            print(obj.toString() + "\n");
        }

        <T> void printArrLn(T[] arr) throws IOException {
            for (int i = 0; i < arr.length - 1; i++) {
                print(arr[i] + " ");
            }
            println(arr[arr.length - 1]);
        }

        <T> void printArr2(T[][] arr) throws IOException {
            for (int j = 0; j < arr.length; j++) {
                for (int i = 0; i < arr[j].length - 1; i++) {
                    print(arr[j][i] + " ");
                }
                println(arr[j][arr.length - 1]);
            }
        }

        <T> void printColl(Collection<T> coll) throws IOException {
            for (T e : coll) {
                print(e + " ");
            }
            println();
        }

        void printCharN(char c, int n) throws IOException {
            for (int i = 0; i < n; i++) {
                print(c);
            }
        }

        void printIntArr2(int[][] arr) throws IOException {
            for (int j = 0; j < arr.length; j++) {
                for (int i = 0; i < arr[j].length - 1; i++) {
                    print(arr[j][i] + " ");
                }
                println(arr[j][arr.length - 1]);
            }
        }

        @Override
        public void close() throws IOException {
            bw.close();
        }

    }

}

import java.io.*;
import java.util.*;
import java.util.function.BinaryOperator;

public class Main {
    private final static long mod = 1000000007;

    private final static int MAXN = 1000001;

    private static long power(long x, long y, long m) {
        long temp;
        if (y == 0)
            return 1;
        temp = power(x, y / 2, m);
        temp = (temp * temp) % m;
        if (y % 2 == 0)
            return temp;
        else
            return ((x % m) * temp) % m;
    }

    private static long power(long x, long y) {
        return power(x, y, mod);
    }

    private static long gcd(long a, long b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

    static int nextPowerOf2(int a) {
        return 1 << nextLog2(a);
    }

    static int nextLog2(int a) {
        return (a == 0 ? 0 : 32 - Integer.numberOfLeadingZeros(a - 1));
    }

    private static long modInverse(long a, long m) {
        long m0 = m;
        long y = 0, x = 1;
        if (m == 1)
            return 0;
        while (a > 1) {
            long q = a / m;
            long t = m;
            m = a % m;
            a = t;
            t = y;
            y = x - q * y;
            x = t;
        }
        if (x < 0)
            x += m0;
        return x;
    }

    private static int[] getLogArr(int n) {
        int arr[] = new int[n + 1];
        for (int i = 1; i < n + 1; i++) {
            arr[i] = (int) (Math.log(i) / Math.log(2) + 1e-10);
        }
        return arr;
    }

    private static int log[] = getLogArr(MAXN);

    private static int getLRSpt(int st[][], int L, int R, BinaryOperator<Integer> binaryOperator) {
        int j = log[R - L + 1];
        return binaryOperator.apply(st[L][j], st[R - (1 << j) + 1][j]);
    }

    private static int[][] getSparseTable(int array[], BinaryOperator<Integer> binaryOperator) {
        int k = log[array.length + 1] + 1;
        int st[][] = new int[array.length + 1][k + 1];

        for (int i = 0; i < array.length; i++)
            st[i][0] = array[i];

        for (int j = 1; j <= k; j++) {
            for (int i = 0; i + (1 << j) <= array.length; i++) {
                st[i][j] = binaryOperator.apply(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
            }
        }
        return st;
    }

    static class Subset {
        int parent;
        int rank;

        @Override
        public String toString() {
            return "" + parent;
        }
    }

    static int find(Subset[] Subsets, int i) {
        if (Subsets[i].parent != i)
            Subsets[i].parent = find(Subsets, Subsets[i].parent);
        return Subsets[i].parent;
    }

    static void union(Subset[] Subsets, int x, int y) {
        int xroot = find(Subsets, x);
        int yroot = find(Subsets, y);

        if (Subsets[xroot].rank < Subsets[yroot].rank)
            Subsets[xroot].parent = yroot;
        else if (Subsets[yroot].rank < Subsets[xroot].rank)
            Subsets[yroot].parent = xroot;
        else {
            Subsets[xroot].parent = yroot;
            Subsets[yroot].rank++;
        }
    }

    private static int maxx(Integer... a) {
        return Collections.max(Arrays.asList(a));
    }

    private static int minn(Integer... a) {
        return Collections.min(Arrays.asList(a));
    }

    private static long maxx(Long... a) {
        return Collections.max(Arrays.asList(a));
    }

    private static long minn(Long... a) {
        return Collections.min(Arrays.asList(a));
    }

    private static class Pair<T, U> implements Comparable<Pair<T, U>> {
        T a;
        U b;

        public Pair(T a, U b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pair pair = (Pair) o;
            return a.equals(pair.a) &&
                    b.equals(pair.b);
        }

        @Override
        public int hashCode() {
            return Objects.hash(a, b);
        }

        @Override
        public String toString() {
            return "(" + a +
                    "," + b +
                    ')';
        }

        @Override
        public int compareTo(Pair<T, U> o) {
            return (int) (this.a.equals(o.a) ?
                    this.b.equals(o.b) ? 0 :
                            ((Integer) this.b - (Integer) o.b) / Math.abs((Integer) this.b - (Integer) o.b) :
                    ((Integer) this.a - (Integer) o.a) / Math.abs((Integer) this.a - (Integer) o.a));
        }
    }

    public static int upperBound(List<Integer> list, int value) {
        int low = 0;
        int high = list.size();
        while (low < high) {
            final int mid = (low + high) / 2;
            if (value >= list.get(mid)) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return low;
    }

    private static int[] getLPSArray(String pattern) {
        int i, j, n = pattern.length();
        int[] lps = new int[pattern.length()];
        lps[0] = 0;
        for (i = 1, j = 0; i < n; ) {
            if (pattern.charAt(i) == pattern.charAt(j)) {
                lps[i++] = ++j;
            } else if (j > 0) {
                j = lps[j - 1];
            } else {
                lps[i++] = 0;
            }
        }
        return lps;
    }

    private static List<Integer> findPattern(String text, String pattern) {
        List<Integer> matchedIndexes = new ArrayList<>();
        if (pattern.length() == 0) {
            return matchedIndexes;
        }
        int[] lps = getLPSArray(pattern);
        int i = 0, j = 0, n = text.length(), m = pattern.length();
        while (i < n) {
            if (text.charAt(i) == pattern.charAt(j)) {
                i++;
                j++;
            }
            if (j == m) {
                matchedIndexes.add(i - j);
                j = lps[j - 1];
            }
            if (i < n && text.charAt(i) != pattern.charAt(j)) {
                if (j > 0) {
                    j = lps[j - 1];
                } else {
                    i++;
                }
            }
        }
        return matchedIndexes;
    }

    private static Set<Long> getDivisors(long n) {
        Set<Long> divisors = new HashSet<>();
        divisors.add(1L);
        divisors.add(n);
        for (long i = 2; i <= Math.sqrt(n); i++) {
            if (n % i == 0) {
                divisors.add(i);
                divisors.add(n / i);
            }
        }
        return divisors;
    }

    private static long getLCM(long a, long b) {
        return (Math.max(a, b) / gcd(a, b)) * Math.min(a, b);
    }

    static long fac[] = new long[2000005];
    static long ifac[] = new long[2000005];

    private static void preCompute(int n) {
        fac = new long[n + 1];
        ifac = new long[n + 1];
        fac[0] = ifac[0] = fac[1] = ifac[1] = 1;
        int i;
        for (i = 2; i < n + 1; i++) {
            fac[i] = (i * fac[i - 1]) % mod;
            ifac[i] = (power(i, mod - 2) * ifac[i - 1]) % mod;
        }
    }

    private static long C(int n, int r) {
        if (n < 0 || r < 0) return 1;
        if (r > n) return 1;
        return (fac[n] * ((ifac[r] * ifac[n - r]) % mod)) % mod;
    }

    static long getSum(long BITree[], int index)
    {
        long sum = 0;
        index = index + 1;
        while(index>0)
        {
            index -= index & (-index);
        }
        return sum;
    }

    public static void updateBIT(long BITree[], int index, long val)
    {
        index = index + 1;
        while(index <= BITree.length-1) {
            BITree[index] += val;
            index += index & (-index);
        }
    }
    long[] constructBITree(int arr[], int m)
    {
        int n=arr.length;
        long BITree[] = new long[m+1];
        for(int i=1; i<=n; i++)
            BITree[i] = 0;
        for(int i = 0; i < n; i++)
            updateBIT(BITree, i, arr[i]);
        return BITree;
    }

    private static int upperBound(int a[], int l, int r, int x) {
        if(l>r)return -1;
        if(l==r){
            if(a[l]<=x) {
                return -1;
            }
            else{
                return a[l];
            }
        }
        int m=(l+r)/2;
        if(a[m]<=x) {
            return upperBound(a, m+1,r,x);
        }
        else {
            return upperBound(a, l,m,x);
        }
    }

    private static long getCntOdd(long x, long y)
    {
        long p2 = 1;
        long ans = 0;
        while (p2 * x <= y)
        {
            long hi = Math.min (y, p2 * (x + 1) - 1);
            ans += hi - p2 * x + 1;
            p2 *= 2;
        }
        return ans;
    }

    private static long getCnt(long x, long y)
    {
        long ans=getCntOdd(x,y);
        if(x%2==0) ans+=getCntOdd(x+1,y);
        //System.out.println(ans);
        return ans;
    }

    private static void mul(long A[][], long B[][]){
        int i,j,k,n=A.length;
        long C[][]=new long[n][n];
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                for(k=0;k<n;k++){
                    C[i][j]=(C[i][j]+(A[i][k]*B[k][j])%mod)%mod;
                }
            }
        }
        for(i=0;i<n;i++) {
            for (j = 0; j < n; j++) {
                A[i][j]=C[i][j];
            }
        }
    }

    private static void power(long A[][], long base[][], long n) {
        if(n<2){
            return;
        }
        power(A, base, n/2);
        mul(A,A);
        if(n%2==1){
            mul(A, base);
        }
    }

    public static void main(String[] args) throws Exception {

        long START_TIME = System.currentTimeMillis();
        try (FastReader in = new FastReader();
             FastWriter out = new FastWriter()) {

            int t, i, j,f, k,m, ti, tidx, gm, q, g;
            //for (t = in.nextInt(), tidx = 1; tidx <= t; tidx++)
            {
                long n,w,x, y = 0, z = 0, sum = 0, bhc = 0, ans = 0,l,r;
                //out.print(String.format("Case #%d: ", tidx));
                n=in.nextLong();
                m=in.nextInt();
                long baseMat[][]=new long[m][m];
                long baseMat1[][]=new long[m][m];
                baseMat1[0][0]=baseMat1[0][m-1]=baseMat[0][0]=baseMat[0][m-1]=1;
                for(i=1,j=0;i<m;i++,j++){
                    baseMat1[i][j]=baseMat[i][j]=1;
                }
                if(n<m){
                    out.println(1);
                }
                power(baseMat, baseMat1, n);
                out.println(baseMat[0][0]);

            }
            if (args.length > 0 && "ex_time".equals(args[0])) {
                out.print("\nTime taken: ");
                out.println(System.currentTimeMillis() - START_TIME);
            }
            out.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static class FastReader implements Closeable {
        private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer st;

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        int[] nextIntArr(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextInt();
            }
            return arr;
        }

        int[] nextIntegerArr(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextInt();
            }
            return arr;
        }

        double[] nextDoubleArr(int n) {
            double[] arr = new double[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextDouble();
            }
            return arr;
        }

        long[] nextLongArr(int n) {
            long[] arr = new long[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLong();
            }
            return arr;
        }

        String[] nextStrArr(int n) {
            String[] arr = new String[n];
            for (int i = 0; i < n; i++) {
                arr[i] = next();
            }
            return arr;
        }

        long[][] nextLongArr2(int n, int m) {
            long[][] arr = new long[n][m];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLongArr(m);
            }
            return arr;
        }

        @Override
        public void close() throws IOException {
            br.close();
        }
    }

    public static class FastWriter implements Closeable {
        BufferedWriter bw;
        StringBuilder sb = new StringBuilder();
        List<String> list = new ArrayList<>();
        Set<String> set = new HashSet<>();

        public FastWriter() {
            bw = new BufferedWriter(new OutputStreamWriter(System.out));
        }

        <T> void commit() throws IOException {
            bw.write(sb.toString());
            bw.flush();
            sb = new StringBuilder();
        }

        public <T> void print(T obj) throws IOException {
            sb.append(obj.toString());
        }

        public void println() throws IOException {
            print("\n");
        }

        public <T> void println(T obj) throws IOException {
            print(obj.toString() + "\n");
        }

        <T> void printArrLn(T[] arr) throws IOException {
            for (int i = 0; i < arr.length - 1; i++) {
                print(arr[i] + " ");
            }
            println(arr[arr.length - 1]);
        }

        <T> void printArr2(T[][] arr) throws IOException {
            for (int j = 0; j < arr.length; j++) {
                for (int i = 0; i < arr[j].length - 1; i++) {
                    print(arr[j][i] + " ");
                }
                println(arr[j][arr.length - 1]);
            }
        }

        <T> void printColl(Collection<T> coll) throws IOException {
            for (T e : coll) {
                print(e + " ");
            }
            println();
        }

        void printCharN(char c, int n) throws IOException {
            for (int i = 0; i < n; i++) {
                print(c);
            }
        }

        void printIntArr2(int[][] arr) throws IOException {
            for (int j = 0; j < arr.length; j++) {
                for (int i = 0; i < arr[j].length - 1; i++) {
                    print(arr[j][i] + " ");
                }
                println(arr[j][arr.length - 1]);
            }
        }

        @Override
        public void close() throws IOException {
            bw.close();
        }

    }

}

import java.io.*;
import java.util.*;
import java.util.function.BinaryOperator;

public class Main {
    private final static long mod = 1000000007;

    private final static int MAXN = 1000001;

    private static long power(long x, long y, long m) {
        long temp;
        if (y == 0)
            return 1;
        temp = power(x, y / 2, m);
        temp = (temp * temp) % m;
        if (y % 2 == 0)
            return temp;
        else
            return ((x % m) * temp) % m;
    }

    private static long power(long x, long y) {
        return power(x, y, mod);
    }

    private static long gcd(long a, long b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

    static int nextPowerOf2(int a) {
        return 1 << nextLog2(a);
    }

    static int nextLog2(int a) {
        return (a == 0 ? 0 : 32 - Integer.numberOfLeadingZeros(a - 1));
    }

    private static long modInverse(long a, long m) {
        long m0 = m;
        long y = 0, x = 1;
        if (m == 1)
            return 0;
        while (a > 1) {
            long q = a / m;
            long t = m;
            m = a % m;
            a = t;
            t = y;
            y = x - q * y;
            x = t;
        }
        if (x < 0)
            x += m0;
        return x;
    }

    private static int[] getLogArr(int n) {
        int arr[] = new int[n + 1];
        for (int i = 1; i < n + 1; i++) {
            arr[i] = (int) (Math.log(i) / Math.log(2) + 1e-10);
        }
        return arr;
    }

    private static int log[] = getLogArr(MAXN);

    private static int getLRSpt(int st[][], int L, int R, BinaryOperator<Integer> binaryOperator) {
        int j = log[R - L + 1];
        return binaryOperator.apply(st[L][j], st[R - (1 << j) + 1][j]);
    }

    private static int[][] getSparseTable(int array[], BinaryOperator<Integer> binaryOperator) {
        int k = log[array.length + 1] + 1;
        int st[][] = new int[array.length + 1][k + 1];

        for (int i = 0; i < array.length; i++)
            st[i][0] = array[i];

        for (int j = 1; j <= k; j++) {
            for (int i = 0; i + (1 << j) <= array.length; i++) {
                st[i][j] = binaryOperator.apply(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
            }
        }
        return st;
    }

    static class Subset {
        int parent;
        int rank;

        @Override
        public String toString() {
            return "" + parent;
        }
    }

    static int find(Subset[] Subsets, int i) {
        if (Subsets[i].parent != i)
            Subsets[i].parent = find(Subsets, Subsets[i].parent);
        return Subsets[i].parent;
    }

    static void union(Subset[] Subsets, int x, int y) {
        int xroot = find(Subsets, x);
        int yroot = find(Subsets, y);

        if (Subsets[xroot].rank < Subsets[yroot].rank)
            Subsets[xroot].parent = yroot;
        else if (Subsets[yroot].rank < Subsets[xroot].rank)
            Subsets[yroot].parent = xroot;
        else {
            Subsets[xroot].parent = yroot;
            Subsets[yroot].rank++;
        }
    }

    private static int maxx(Integer... a) {
        return Collections.max(Arrays.asList(a));
    }

    private static int minn(Integer... a) {
        return Collections.min(Arrays.asList(a));
    }

    private static long maxx(Long... a) {
        return Collections.max(Arrays.asList(a));
    }

    private static long minn(Long... a) {
        return Collections.min(Arrays.asList(a));
    }

    private static class Pair<T, U> implements Comparable<Pair<T, U>> {
        T a;
        U b;

        public Pair(T a, U b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pair pair = (Pair) o;
            return a.equals(pair.a) &&
                    b.equals(pair.b);
        }

        @Override
        public int hashCode() {
            return Objects.hash(a, b);
        }

        @Override
        public String toString() {
            return "(" + a +
                    "," + b +
                    ')';
        }

        @Override
        public int compareTo(Pair<T, U> o) {
            return (int) (this.a.equals(o.a) ?
                    this.b.equals(o.b) ? 0 :
                            ((Integer) this.b - (Integer) o.b) / Math.abs((Integer) this.b - (Integer) o.b) :
                    ((Integer) this.a - (Integer) o.a) / Math.abs((Integer) this.a - (Integer) o.a));
        }
    }

    public static int upperBound(List<Integer> list, int value) {
        int low = 0;
        int high = list.size();
        while (low < high) {
            final int mid = (low + high) / 2;
            if (value >= list.get(mid)) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return low;
    }

    private static int[] getLPSArray(String pattern) {
        int i, j, n = pattern.length();
        int[] lps = new int[pattern.length()];
        lps[0] = 0;
        for (i = 1, j = 0; i < n; ) {
            if (pattern.charAt(i) == pattern.charAt(j)) {
                lps[i++] = ++j;
            } else if (j > 0) {
                j = lps[j - 1];
            } else {
                lps[i++] = 0;
            }
        }
        return lps;
    }

    private static List<Integer> findPattern(String text, String pattern) {
        List<Integer> matchedIndexes = new ArrayList<>();
        if (pattern.length() == 0) {
            return matchedIndexes;
        }
        int[] lps = getLPSArray(pattern);
        int i = 0, j = 0, n = text.length(), m = pattern.length();
        while (i < n) {
            if (text.charAt(i) == pattern.charAt(j)) {
                i++;
                j++;
            }
            if (j == m) {
                matchedIndexes.add(i - j);
                j = lps[j - 1];
            }
            if (i < n && text.charAt(i) != pattern.charAt(j)) {
                if (j > 0) {
                    j = lps[j - 1];
                } else {
                    i++;
                }
            }
        }
        return matchedIndexes;
    }

    private static Set<Long> getDivisors(long n) {
        Set<Long> divisors = new HashSet<>();
        divisors.add(1L);
        divisors.add(n);
        for (long i = 2; i <= Math.sqrt(n); i++) {
            if (n % i == 0) {
                divisors.add(i);
                divisors.add(n / i);
            }
        }
        return divisors;
    }

    private static long getLCM(long a, long b) {
        return (Math.max(a, b) / gcd(a, b)) * Math.min(a, b);
    }

    static long fac[] = new long[2000005];
    static long ifac[] = new long[2000005];

    private static void preCompute(int n) {
        fac = new long[n + 1];
        ifac = new long[n + 1];
        fac[0] = ifac[0] = fac[1] = ifac[1] = 1;
        int i;
        for (i = 2; i < n + 1; i++) {
            fac[i] = (i * fac[i - 1]) % mod;
            ifac[i] = (power(i, mod - 2) * ifac[i - 1]) % mod;
        }
    }

    private static long C(int n, int r) {
        if (n < 0 || r < 0) return 1;
        if (r > n) return 1;
        return (fac[n] * ((ifac[r] * ifac[n - r]) % mod)) % mod;
    }

    static long getSum(long BITree[], int index)
    {
        long sum = 0;
        index = index + 1;
        while(index>0)
        {
            index -= index & (-index);
        }
        return sum;
    }

    public static void updateBIT(long BITree[], int index, long val)
    {
        index = index + 1;
        while(index <= BITree.length-1) {
            BITree[index] += val;
            index += index & (-index);
        }
    }
    long[] constructBITree(int arr[], int m)
    {
        int n=arr.length;
        long BITree[] = new long[m+1];
        for(int i=1; i<=n; i++)
            BITree[i] = 0;
        for(int i = 0; i < n; i++)
            updateBIT(BITree, i, arr[i]);
        return BITree;
    }

    private static int upperBound(int a[], int l, int r, int x) {
        if(l>r)return -1;
        if(l==r){
            if(a[l]<=x) {
                return -1;
            }
            else{
                return a[l];
            }
        }
        int m=(l+r)/2;
        if(a[m]<=x) {
            return upperBound(a, m+1,r,x);
        }
        else {
            return upperBound(a, l,m,x);
        }
    }

    private static long getCntOdd(long x, long y)
    {
        long p2 = 1;
        long ans = 0;
        while (p2 * x <= y)
        {
            long hi = Math.min (y, p2 * (x + 1) - 1);
            ans += hi - p2 * x + 1;
            p2 *= 2;
        }
        return ans;
    }

    private static long getCnt(long x, long y)
    {
        long ans=getCntOdd(x,y);
        if(x%2==0) ans+=getCntOdd(x+1,y);
        //System.out.println(ans);
        return ans;
    }

    private static void mul(long A[][], long B[][]){
        int i,j,k,n=A.length;
        long C[][]=new long[n][n];
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                for(k=0;k<n;k++){
                    C[i][j]=(C[i][j]+A[i][k]*B[k][j])%mod;
                }
            }
        }
        for(i=0;i<n;i++) {
            for (j = 0; j < n; j++) {
                A[i][j]=C[i][j];
            }
        }
    }

    private static void power(long A[][], long base[][], long n) {
        if(n<2){
            return;
        }
        power(A, base, n/2);
        mul(A,A);
        if(n%2==1){
            mul(A, base);
        }
    }

    public static void main(String[] args) throws Exception {

        long START_TIME = System.currentTimeMillis();
        try (FastReader in = new FastReader();
             FastWriter out = new FastWriter()) {

            int t, i, j,f, k,m, ti, tidx, gm, q, g;
            //for (t = in.nextInt(), tidx = 1; tidx <= t; tidx++)
            {
                long n,w,x, y = 0, z = 0, sum = 0, bhc = 0, ans = 0,l,r;
                //out.print(String.format("Case #%d: ", tidx));
                n=in.nextLong();
                m=in.nextInt();
                long baseMat[][]=new long[m+1][m+1];
                long baseMat1[][]=new long[m+1][m+1];
                baseMat1[0][0]=baseMat1[0][m]=baseMat[0][0]=baseMat[0][m]=1;
                for(i=1,j=0;i<=m;i++,j++){
                    baseMat1[i][j]=baseMat[i][j]=1;
                }
                if(n<m){
                    out.println(1);
                }
                power(baseMat, baseMat1, n);
                out.println((baseMat[0][0]+baseMat[0][m])%mod);

            }
            if (args.length > 0 && "ex_time".equals(args[0])) {
                out.print("\nTime taken: ");
                out.println(System.currentTimeMillis() - START_TIME);
            }
            out.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static class FastReader implements Closeable {
        private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer st;

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        int[] nextIntArr(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextInt();
            }
            return arr;
        }

        int[] nextIntegerArr(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextInt();
            }
            return arr;
        }

        double[] nextDoubleArr(int n) {
            double[] arr = new double[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextDouble();
            }
            return arr;
        }

        long[] nextLongArr(int n) {
            long[] arr = new long[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLong();
            }
            return arr;
        }

        String[] nextStrArr(int n) {
            String[] arr = new String[n];
            for (int i = 0; i < n; i++) {
                arr[i] = next();
            }
            return arr;
        }

        long[][] nextLongArr2(int n, int m) {
            long[][] arr = new long[n][m];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLongArr(m);
            }
            return arr;
        }

        @Override
        public void close() throws IOException {
            br.close();
        }
    }

    public static class FastWriter implements Closeable {
        BufferedWriter bw;
        StringBuilder sb = new StringBuilder();
        List<String> list = new ArrayList<>();
        Set<String> set = new HashSet<>();

        public FastWriter() {
            bw = new BufferedWriter(new OutputStreamWriter(System.out));
        }

        <T> void commit() throws IOException {
            bw.write(sb.toString());
            bw.flush();
            sb = new StringBuilder();
        }

        public <T> void print(T obj) throws IOException {
            sb.append(obj.toString());
        }

        public void println() throws IOException {
            print("\n");
        }

        public <T> void println(T obj) throws IOException {
            print(obj.toString() + "\n");
        }

        <T> void printArrLn(T[] arr) throws IOException {
            for (int i = 0; i < arr.length - 1; i++) {
                print(arr[i] + " ");
            }
            println(arr[arr.length - 1]);
        }

        <T> void printArr2(T[][] arr) throws IOException {
            for (int j = 0; j < arr.length; j++) {
                for (int i = 0; i < arr[j].length - 1; i++) {
                    print(arr[j][i] + " ");
                }
                println(arr[j][arr.length - 1]);
            }
        }

        <T> void printColl(Collection<T> coll) throws IOException {
            for (T e : coll) {
                print(e + " ");
            }
            println();
        }

        void printCharN(char c, int n) throws IOException {
            for (int i = 0; i < n; i++) {
                print(c);
            }
        }

        void printIntArr2(int[][] arr) throws IOException {
            for (int j = 0; j < arr.length; j++) {
                for (int i = 0; i < arr[j].length - 1; i++) {
                    print(arr[j][i] + " ");
                }
                println(arr[j][arr.length - 1]);
            }
        }

        @Override
        public void close() throws IOException {
            bw.close();
        }

    }

}

import java.io.*;
import java.util.*;
import java.util.function.BinaryOperator;

public class Main {
    private final static long mod = 1000000007;

    private final static int MAXN = 1000001;

    private static long power(long x, long y, long m) {
        long temp;
        if (y == 0)
            return 1;
        temp = power(x, y / 2, m);
        temp = (temp * temp) % m;
        if (y % 2 == 0)
            return temp;
        else
            return ((x % m) * temp) % m;
    }

    private static long power(long x, long y) {
        return power(x, y, mod);
    }

    private static long gcd(long a, long b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

    static int nextPowerOf2(int a) {
        return 1 << nextLog2(a);
    }

    static int nextLog2(int a) {
        return (a == 0 ? 0 : 32 - Integer.numberOfLeadingZeros(a - 1));
    }

    private static long modInverse(long a, long m) {
        long m0 = m;
        long y = 0, x = 1;
        if (m == 1)
            return 0;
        while (a > 1) {
            long q = a / m;
            long t = m;
            m = a % m;
            a = t;
            t = y;
            y = x - q * y;
            x = t;
        }
        if (x < 0)
            x += m0;
        return x;
    }

    private static int[] getLogArr(int n) {
        int arr[] = new int[n + 1];
        for (int i = 1; i < n + 1; i++) {
            arr[i] = (int) (Math.log(i) / Math.log(2) + 1e-10);
        }
        return arr;
    }

    private static int log[] = getLogArr(MAXN);

    private static int getLRSpt(int st[][], int L, int R, BinaryOperator<Integer> binaryOperator) {
        int j = log[R - L + 1];
        return binaryOperator.apply(st[L][j], st[R - (1 << j) + 1][j]);
    }

    private static int[][] getSparseTable(int array[], BinaryOperator<Integer> binaryOperator) {
        int k = log[array.length + 1] + 1;
        int st[][] = new int[array.length + 1][k + 1];

        for (int i = 0; i < array.length; i++)
            st[i][0] = array[i];

        for (int j = 1; j <= k; j++) {
            for (int i = 0; i + (1 << j) <= array.length; i++) {
                st[i][j] = binaryOperator.apply(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
            }
        }
        return st;
    }

    static class Subset {
        int parent;
        int rank;

        @Override
        public String toString() {
            return "" + parent;
        }
    }

    static int find(Subset[] Subsets, int i) {
        if (Subsets[i].parent != i)
            Subsets[i].parent = find(Subsets, Subsets[i].parent);
        return Subsets[i].parent;
    }

    static void union(Subset[] Subsets, int x, int y) {
        int xroot = find(Subsets, x);
        int yroot = find(Subsets, y);

        if (Subsets[xroot].rank < Subsets[yroot].rank)
            Subsets[xroot].parent = yroot;
        else if (Subsets[yroot].rank < Subsets[xroot].rank)
            Subsets[yroot].parent = xroot;
        else {
            Subsets[xroot].parent = yroot;
            Subsets[yroot].rank++;
        }
    }

    private static int maxx(Integer... a) {
        return Collections.max(Arrays.asList(a));
    }

    private static int minn(Integer... a) {
        return Collections.min(Arrays.asList(a));
    }

    private static long maxx(Long... a) {
        return Collections.max(Arrays.asList(a));
    }

    private static long minn(Long... a) {
        return Collections.min(Arrays.asList(a));
    }

    private static class Pair<T, U> implements Comparable<Pair<T, U>> {
        T a;
        U b;

        public Pair(T a, U b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pair pair = (Pair) o;
            return a.equals(pair.a) &&
                    b.equals(pair.b);
        }

        @Override
        public int hashCode() {
            return Objects.hash(a, b);
        }

        @Override
        public String toString() {
            return "(" + a +
                    "," + b +
                    ')';
        }

        @Override
        public int compareTo(Pair<T, U> o) {
            return (int) (this.a.equals(o.a) ?
                    this.b.equals(o.b) ? 0 :
                            ((Integer) this.b - (Integer) o.b) / Math.abs((Integer) this.b - (Integer) o.b) :
                    ((Integer) this.a - (Integer) o.a) / Math.abs((Integer) this.a - (Integer) o.a));
        }
    }

    public static int upperBound(List<Integer> list, int value) {
        int low = 0;
        int high = list.size();
        while (low < high) {
            final int mid = (low + high) / 2;
            if (value >= list.get(mid)) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return low;
    }

    private static int[] getLPSArray(String pattern) {
        int i, j, n = pattern.length();
        int[] lps = new int[pattern.length()];
        lps[0] = 0;
        for (i = 1, j = 0; i < n; ) {
            if (pattern.charAt(i) == pattern.charAt(j)) {
                lps[i++] = ++j;
            } else if (j > 0) {
                j = lps[j - 1];
            } else {
                lps[i++] = 0;
            }
        }
        return lps;
    }

    private static List<Integer> findPattern(String text, String pattern) {
        List<Integer> matchedIndexes = new ArrayList<>();
        if (pattern.length() == 0) {
            return matchedIndexes;
        }
        int[] lps = getLPSArray(pattern);
        int i = 0, j = 0, n = text.length(), m = pattern.length();
        while (i < n) {
            if (text.charAt(i) == pattern.charAt(j)) {
                i++;
                j++;
            }
            if (j == m) {
                matchedIndexes.add(i - j);
                j = lps[j - 1];
            }
            if (i < n && text.charAt(i) != pattern.charAt(j)) {
                if (j > 0) {
                    j = lps[j - 1];
                } else {
                    i++;
                }
            }
        }
        return matchedIndexes;
    }

    private static Set<Long> getDivisors(long n) {
        Set<Long> divisors = new HashSet<>();
        divisors.add(1L);
        divisors.add(n);
        for (long i = 2; i <= Math.sqrt(n); i++) {
            if (n % i == 0) {
                divisors.add(i);
                divisors.add(n / i);
            }
        }
        return divisors;
    }

    private static long getLCM(long a, long b) {
        return (Math.max(a, b) / gcd(a, b)) * Math.min(a, b);
    }

    static long fac[] = new long[2000005];
    static long ifac[] = new long[2000005];

    private static void preCompute(int n) {
        fac = new long[n + 1];
        ifac = new long[n + 1];
        fac[0] = ifac[0] = fac[1] = ifac[1] = 1;
        int i;
        for (i = 2; i < n + 1; i++) {
            fac[i] = (i * fac[i - 1]) % mod;
            ifac[i] = (power(i, mod - 2) * ifac[i - 1]) % mod;
        }
    }

    private static long C(int n, int r) {
        if (n < 0 || r < 0) return 1;
        if (r > n) return 1;
        return (fac[n] * ((ifac[r] * ifac[n - r]) % mod)) % mod;
    }

    static long getSum(long BITree[], int index)
    {
        long sum = 0;
        index = index + 1;
        while(index>0)
        {
            index -= index & (-index);
        }
        return sum;
    }

    public static void updateBIT(long BITree[], int index, long val)
    {
        index = index + 1;
        while(index <= BITree.length-1) {
            BITree[index] += val;
            index += index & (-index);
        }
    }
    long[] constructBITree(int arr[], int m)
    {
        int n=arr.length;
        long BITree[] = new long[m+1];
        for(int i=1; i<=n; i++)
            BITree[i] = 0;
        for(int i = 0; i < n; i++)
            updateBIT(BITree, i, arr[i]);
        return BITree;
    }

    private static int upperBound(int a[], int l, int r, int x) {
        if(l>r)return -1;
        if(l==r){
            if(a[l]<=x) {
                return -1;
            }
            else{
                return a[l];
            }
        }
        int m=(l+r)/2;
        if(a[m]<=x) {
            return upperBound(a, m+1,r,x);
        }
        else {
            return upperBound(a, l,m,x);
        }
    }

    private static long getCntOdd(long x, long y)
    {
        long p2 = 1;
        long ans = 0;
        while (p2 * x <= y)
        {
            long hi = Math.min (y, p2 * (x + 1) - 1);
            ans += hi - p2 * x + 1;
            p2 *= 2;
        }
        return ans;
    }

    private static long getCnt(long x, long y)
    {
        long ans=getCntOdd(x,y);
        if(x%2==0) ans+=getCntOdd(x+1,y);
        //System.out.println(ans);
        return ans;
    }

    private static void mul(long A[][], long B[][]){
        int i,j,k,n=A.length;
        long C[][]=new long[n][n];
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                for(k=0;k<n;k++){
                    C[i][j]=(C[i][j]+(A[i][k]*B[k][j])%mod)%mod;
                }
            }
        }
        for(i=0;i<n;i++) {
            for (j = 0; j < n; j++) {
                A[i][j]=C[i][j];
            }
        }
    }

    private static void power(long A[][], long base[][], long n) {
        if(n<2){
            return;
        }
        power(A, base, n/2);
        mul(A,A);
        if(n%2==1){
            mul(A, base);
        }
    }

    public static void main(String[] args) throws Exception {

        long START_TIME = System.currentTimeMillis();
        try (FastReader in = new FastReader();
             FastWriter out = new FastWriter()) {

            int t, i, j,f, k,m, ti, tidx, gm, q, g;
            //for (t = in.nextInt(), tidx = 1; tidx <= t; tidx++)
            {
                long n,w,x, y = 0, z = 0, sum = 0, bhc = 0, ans = 0,l,r;
                //out.print(String.format("Case #%d: ", tidx));
                n=in.nextLong();
                m=in.nextInt();
                long baseMat[][]=new long[m][m];
                long baseMat1[][]=new long[m][m];
                baseMat1[0][0]=baseMat1[0][m-1]=baseMat[0][0]=baseMat[0][m-1]=1;
                for(i=1,j=0;i<m;i++,j++){
                    baseMat1[i][j]=baseMat[i][j]=1;
                }
                if(n<m){
                    out.println(1);
                }
                power(baseMat, baseMat1, n-1);
                out.println((baseMat[0][0]+baseMat[0][m-1])%mod);

            }
            if (args.length > 0 && "ex_time".equals(args[0])) {
                out.print("\nTime taken: ");
                out.println(System.currentTimeMillis() - START_TIME);
            }
            out.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static class FastReader implements Closeable {
        private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer st;

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        int[] nextIntArr(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextInt();
            }
            return arr;
        }

        int[] nextIntegerArr(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextInt();
            }
            return arr;
        }

        double[] nextDoubleArr(int n) {
            double[] arr = new double[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextDouble();
            }
            return arr;
        }

        long[] nextLongArr(int n) {
            long[] arr = new long[n];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLong();
            }
            return arr;
        }

        String[] nextStrArr(int n) {
            String[] arr = new String[n];
            for (int i = 0; i < n; i++) {
                arr[i] = next();
            }
            return arr;
        }

        long[][] nextLongArr2(int n, int m) {
            long[][] arr = new long[n][m];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLongArr(m);
            }
            return arr;
        }

        @Override
        public void close() throws IOException {
            br.close();
        }
    }

    public static class FastWriter implements Closeable {
        BufferedWriter bw;
        StringBuilder sb = new StringBuilder();
        List<String> list = new ArrayList<>();
        Set<String> set = new HashSet<>();

        public FastWriter() {
            bw = new BufferedWriter(new OutputStreamWriter(System.out));
        }

        <T> void commit() throws IOException {
            bw.write(sb.toString());
            bw.flush();
            sb = new StringBuilder();
        }

        public <T> void print(T obj) throws IOException {
            sb.append(obj.toString());
        }

        public void println() throws IOException {
            print("\n");
        }

        public <T> void println(T obj) throws IOException {
            print(obj.toString() + "\n");
        }

        <T> void printArrLn(T[] arr) throws IOException {
            for (int i = 0; i < arr.length - 1; i++) {
                print(arr[i] + " ");
            }
            println(arr[arr.length - 1]);
        }

        <T> void printArr2(T[][] arr) throws IOException {
            for (int j = 0; j < arr.length; j++) {
                for (int i = 0; i < arr[j].length - 1; i++) {
                    print(arr[j][i] + " ");
                }
                println(arr[j][arr.length - 1]);
            }
        }

        <T> void printColl(Collection<T> coll) throws IOException {
            for (T e : coll) {
                print(e + " ");
            }
            println();
        }

        void printCharN(char c, int n) throws IOException {
            for (int i = 0; i < n; i++) {
                print(c);
            }
        }

        void printIntArr2(int[][] arr) throws IOException {
            for (int j = 0; j < arr.length; j++) {
                for (int i = 0; i < arr[j].length - 1; i++) {
                    print(arr[j][i] + " ");
                }
                println(arr[j][arr.length - 1]);
            }
        }

        @Override
        public void close() throws IOException {
            bw.close();
        }

    }

}

import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class Main {
    static final long MOD = 1_000_000_007, INF = 1_000_000_000_000_000_000L;
    static final int INf = 1_000_000_000;
    static FastReader reader;
    static PrintWriter writer;
    public static void main(String[] args) {
        Thread t = new Thread(null, new O(), "Integer.MAX_VALUE", 100000000);
        t.start();
    }
    static class O implements Runnable {
        public void run() {
            try {
                magic();
            }
            catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    }
    static class FastReader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public FastReader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public FastReader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[1000000];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
    static void magic() throws IOException{
        reader = new FastReader();
        writer = new PrintWriter(System.out, true);
        long N = reader.nextLong();
        int M = reader.nextInt();
        long a[] = new long[M+1];
        a[0] = a[M] = 1;
        long f[] = new long[M];
        Arrays.fill(f, 1);
        writer.println(findNthTerm(N, a, f, M, 0));
    }

    /**
     *
     * @param N
     * @param a the array a[] representing the coefficients a1,a2,a3,...ak
     * @param d the constant term in the recurrence
     * @param f the initial k values of the function i.e. f(0), f(1), f(2)....f(k-1)
     * @returns the Nth term of the recurrence: f(n) = a1*f(n-1) + a2*f(n-2) + ... + ak*f(n-k) + d
     * Complexity: O(k^3 * log(N))
     */
    static long findNthTerm(long N, long a[], long f[], int k, long d) {
        long mat[][] = new long[k+1][k+1];
        mat[0][0] = 1;
        for(int col=1;col<=k;++col) {
            if(col==k) {
                mat[0][col] = d;
                for(int row=1;row<=k;++row) {
                    mat[row][col] = 1;
                }
            }
            else {
                mat[col+1][col] = 1;
            }
        }
        if(N<k) {
           return f[(int)N];
        }
        else {
            long M[][] = exponentiateMatrix(mat, k+1, N-k+1);
            long res[] = new long[k+1];
            for(int i=0;i<=k;++i) {
                long multiplier;
                if(i==0) {
                    multiplier = 1;
                }
                else {
                    multiplier = f[i-1];
                }
                for(int j=0;j<=k;++j) {
                    res[i] = (res[i] + multiplier * M[j][i])%MOD;
                }
            }
            return res[k];
        }
    }

    /**
     *
     * @param a
     * @param b
     * @param k
     * @return the product of the two (k*k) matrices a and b
     */
    static long[][] multiply(long a[][], long b[][], int k) {
        long c[][] = new long[k][k];
        for(int i=0;i<k;++i) {
            for(int j=0;j<k;++j) {
                for(int K=0;K<k;++K) {
                    c[i][j] = (c[i][j] + a[i][K]*b[K][j])%MOD;
                }
            }
        }
        return c;
    }

    /**
     *
     * @param mat
     * @param k
     * @param n
     * @return Finds the matrix: mat^n, here mat is a (k*k) matrix
     */
    static long[][] exponentiateMatrix(long mat[][], int k, long n) {
        if(n==1) {
            return mat;
        }
        if(n%2==0) {
            long half[][] = exponentiateMatrix(mat, k, n/2);
            return multiply(half, half, k);
        }
        return multiply(mat, exponentiateMatrix(mat,k, n-1), k);
    }
}

import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class Main {
    static final long MOD = 1_000_000_007, INF = 1_000_000_000_000_000_000L;
    static final int INf = 1_000_000_000;
    static FastReader reader;
    static PrintWriter writer;
    public static void main(String[] args) {
        Thread t = new Thread(null, new O(), "Integer.MAX_VALUE", 100000000);
        t.start();
    }
    static class O implements Runnable {
        public void run() {
            try {
                magic();
            }
            catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    }
    static class FastReader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public FastReader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public FastReader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[1000000];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
    static void magic() throws IOException{
        reader = new FastReader();
        writer = new PrintWriter(System.out, true);
        long N = reader.nextLong();
        int M = reader.nextInt();
        long a[] = new long[M+1];
        a[0] = a[M] = 1;
        long f[] = new long[M];
        Arrays.fill(f, 1);
        writer.println(findNthTerm(N, a, f, M, 0));
    }

    /**
     *
     * @param N
     * @param a the array a[] representing the coefficients a1,a2,a3,...ak
     * @param d the constant term in the recurrence
     * @param f the initial k values of the function i.e. f(0), f(1), f(2)....f(k-1)
     * @returns the Nth term of the recurrence: f(n) = a1*f(n-1) + a2*f(n-2) + ... + ak*f(n-k) + d
     * Complexity: O(k^3 * log(N))
     */
    static long findNthTerm(long N, long a[], long f[], int k, long d) {
        long mat[][] = new long[k+1][k+1];
        mat[0][0] = 1;
        for(int col=1;col<=k;++col) {
            if(col==k) {
                mat[0][col] = d;
                for(int row=1;row<=k;++row) {
                    mat[row][col] = 1;
                }
            }
            else {
                mat[col+1][col] = 1;
            }
        }
        if(N<k) {
           return f[(int)k];
        }
        else {
            long M[][] = exponentiateMatrix(mat, k+1, N-k+1);
            long res[] = new long[k+1];
            for(int i=0;i<=k;++i) {
                long multiplier;
                if(i==0) {
                    multiplier = 1;
                }
                else {
                    multiplier = f[i-1];
                }
                for(int j=0;j<=k;++j) {
                    res[i] = (res[i] + multiplier * M[j][i])%MOD;
                }
            }
            return res[k];
        }
    }

    /**
     *
     * @param a
     * @param b
     * @param k
     * @return the product of the two (k*k) matrices a and b
     */
    static long[][] multiply(long a[][], long b[][], int k) {
        long c[][] = new long[k][k];
        for(int i=0;i<k;++i) {
            for(int j=0;j<k;++j) {
                for(int K=0;K<k;++K) {
                    c[i][j] = (c[i][j] + a[i][K]*b[K][j]);
                    if(c[i][j]>=MOD) {
                        c[i][j]-=MOD;
                    }
                }
            }
        }
        return c;
    }

    /**
     *
     * @param mat
     * @param k
     * @param n
     * @return Finds the matrix: mat^n, here mat is a (k*k) matrix
     */
    static long[][] exponentiateMatrix(long mat[][], int k, long n) {
        if(n==1) {
            return mat;
        }
        if(n%2==0) {
            long half[][] = exponentiateMatrix(mat, k, n/2);
            return multiply(half, half, k);
        }
        return multiply(mat, exponentiateMatrix(mat,k, n-1), k);
    }
}

import java.util.*;

public class D1117 {
	static long[][] transition;
	static int m;
	static long mod = (long) (10e9 + 9);

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		long n = in.nextLong();
		m = in.nextInt();
		transition = new long[m][m];
		transition[0][0] = 1;
		transition[0][m - 1] = 1;
		for (int i = 0; i < m -1; i++) {
			transition[i+1][i] = 1;
		}
		//System.out.println(Arrays.deepToString(transition));
		long[][] initial = Arrays.copyOf(transition, m);
		long[][] ans = fmp(initial, n);
		//System.out.println(Arrays.deepToString(ans));
		System.out.println(ans[0][0]);
	}

	static long[][] fmp(long[][] matrix, long pow) {
		//System.out.println("cur pow: " + pow);
		//System.out.println(Arrays.deepToString(matrix));
		if (pow == 1)
			return matrix;

		matrix = fmp(matrix, pow / 2);
		long[][] next = new long[m][m];
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < m; j++) {
				long sum = 0;
				for (int k = 0; k < m; k++) {
					sum += matrix[i][k] * matrix[k][j];
					sum %= mod;
				}
				next[i][j] = sum;
			}
		}
		if(pow % 2 == 0) {
			return next;
		}

		long[][] n2 = new long[m][m];
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < m; j++) {
				long sum = 0;
				for (int k = 0; k < m; k++) {
					sum += next[i][k] * transition[k][j];
					sum %= mod;
				}
				n2[i][j] = sum;
			}
		}

		return n2;

	}

}

import java.util.*;

public class D1117 {
	static long[][] transition;
	static int m;
	static long mod = (long) (10e9 + 9);

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		long n = in.nextLong();
		m = in.nextInt();
		transition = new long[m][m];
		transition[0][0] = 1;
		transition[0][m - 1] = 1;
		for (int i = 0; i < m -1; i++) {
			transition[i+1][i] = 1;
		}
		//System.out.println(Arrays.deepToString(transition));
		long[][] initial = Arrays.copyOf(transition, m);
		long[][] ans = fmp(initial, n);
		//System.out.println(Arrays.deepToString(ans));
		System.out.println(ans[0][0]);
	}

	static long[][] fmp(long[][] matrix, long pow) {
		//System.out.println("cur pow: " + pow);
		//System.out.println(Arrays.deepToString(matrix));
		if (pow == 1)
			return matrix;

		matrix = fmp(matrix, pow / 2);
		long[][] next = new long[m][m];
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < m; j++) {
				long sum = 0;
				for (int k = 0; k < m; k++) {
					sum += (matrix[i][k] * matrix[k][j])%mod;
					sum %= mod;
				}
				next[i][j] = sum;
			}
		}
		if(pow % 2 == 0) {
			return next;
		}

		long[][] n2 = new long[m][m];
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < m; j++) {
				long sum = 0;
				for (int k = 0; k < m; k++) {
					sum += (next[i][k] * transition[k][j])%mod;
					sum %= mod;
				}
				n2[i][j] = sum;
			}
		}

		return n2;

	}

}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author real
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        long mod;
        long[][] firstm;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long n = in.nextLong();
            int m = in.nextInt();
            mod = in.mod1e97;
            firstm = new long[m][1];
            for (int i = 0; i < m; i++) {
                firstm[i][0] = 1;
            }
            if (n < m) {
                out.print(firstm[(int) n][0]);
                return;
            }
            long matrix[][] = new long[m][m];
            for (int i = 1; i < m; i++) {
                matrix[i][i - 1] = 1;
            }
            matrix[0][m - 1] = 1;
            matrix[0][0] = 1;
            long po = n - m + 1;
            long ans[][] = pow(matrix, po);
            long ans2[][] = multiply(ans, firstm);
            out.print(ans2[0][0]);
            out.print("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
        }

        long[][] pow(long matrix[][], long m) {
            if (m == 1)
                return matrix;
            if (m % 2 == 0) {
                long mat[][] = pow(matrix, m / 2);
                return multiply(mat, mat);
            }
            return multiply(matrix, pow(matrix, m - 1));
        }

        long[][] multiply(long matrix1[][], long matrix2[][]) {
            long ans[][] = new long[matrix1.length][matrix2[0].length];
            for (int i = 0; i < matrix1.length; i++) {
                for (int j = 0; j < matrix2[0].length; j++) {
                    for (int k = 0; k < matrix1[0].length; k++) {
                        ans[i][j] += (matrix1[i][k] * matrix2[k][j]) % mod;
                        ans[i][j] = ans[i][j] % mod;
                    }
                }
            }
            return ans;
        }

    }

    static class InputReader {
        private final InputStream stream;
        private final byte[] buf = new byte[8192];
        private int curChar;
        private int snumChars;
        int mod1e97 = (int) 1e9 + 7;

        public InputReader(InputStream st) {
            this.stream = st;
        }

        public int read() {
            //*-*------clare------
//remeber while comparing 2 non primitive data type not to use ==
//remember Arrays.sort for primitive data has worst time case complexity of 0(n^2) bcoz it uses quick sort
//again silly mistakes ,yr kb tk krta rhega ye mistakes
//try to write simple codes ,break it into simple things
            // for test cases make sure println(); ;)
//knowledge>rating
        /*
        public class Main
        implements Runnable{
    public static void main(String[] args) {
        new Thread(null,new Main(),"Main",1<<26).start();

    }
    public void run() {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskC solver = new TaskC();//chenge the name of task
        solver.solve(1, in, out);
        out.close();
    }
         */

            if (snumChars == -1)
                throw new InputMismatchException();
            if (curChar >= snumChars) {
                curChar = 0;
                try {
                    snumChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (snumChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

    }
}

import java.util.*;
import java.io.*;
/*
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
Integer.parseInt(st.nextToken());
Long.parseLong(st.nextToken());
Scanner sc = new Scanner(System.in);

*/

public class Waw{

    public static void main(String[] args) throws Exception{

        Scanner sc = new Scanner(System.in);
        long n = sc.nextLong();
        long m = sc.nextLong();
        long M = (long)Math.pow(10,9) + (long)7;
        long k = n/m;
        long rep = 0;
        if(n%m==0) {
            k--;
            rep++;

        }
        k%=M;
        n%=M;
        m%=M;
        rep += 1 + ((n*k)%M) - ((((k*k)%M)*m)%M) + k;
        rep %= M;

        System.out.println(rep);

    }
}

import java.util.*;
import java.io.*;
public class EdB {
	static long[] mods = {1000000007, 998244353, 1000000009};
	static long mod = mods[0];
	public static MyScanner sc;
    public static PrintWriter out;
    static long[][] matrix;
    static int m;
	public static void main(String[] omkar) throws Exception{
		// TODO Auto-generated method stub
 		sc = new MyScanner();
 		PrintWriter out = new PrintWriter(System.out);
 		long n = sc.nextLong();
 		m = sc.nextInt();
 		matrix = new long[m][m];
 		matrix[0][0] = 1;
 		matrix[0][m-1] = 1;
 		for(int j =1;j<m;j++){
 			matrix[j][j-1] = 1;
 		}
 		long[][] newm = new long[m][m];
 		if (n >= m)
 			newm = power(matrix, n-(long)m);
 		long ans = (2L*newm[0][0]+newm[0][m-1])%mod;
 		out.println(ans);

 		out.close();
 	}
	public static long[][] mul(long[][] m1, long[][] m2){
		long[][] ans = new long[m][m];
		for(int j =0;j<m;j++){
			for(int k = 0;k<m;k++){
				long sum = 0;
				for(int l = 0;l<m;l++){
					sum+=m1[j][l]*m2[l][k];
					sum%=mod;
				}
				ans[j][k] = sum;
			}
		}
		return ans;
	}
	public static long[][] power(long[][] m1, long k){

		if (k == 0){
			long[][] mst = new long[m][m];
			for(int j =0 ;j<m;j++){
				mst[j][j] = 1L;
			}
			return mst;
		}

		if (k == 1)
			return m1;
		long [][]ks = power(m1, k/2);
		if (k%2 == 0)
			return mul(ks, ks);
		else
			return mul(mul(ks, ks), m1);
	}
	public static void sort(int[] array){
		ArrayList<Integer> copy = new ArrayList<Integer>();
		for (int i : array)
			copy.add(i);
		Collections.sort(copy);
		for(int i = 0;i<array.length;i++)
			array[i] = copy.get(i);
	}
	static String[] readArrayString(int n){
		String[] array = new String[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.next();
		return array;
	}
	static int[] readArrayInt(int n){
    	int[] array = new int[n];
    	for(int j = 0;j<n;j++)
    		array[j] = sc.nextInt();
    	return array;
    }
	static int[] readArrayInt1(int n){
		int[] array = new int[n+1];
		for(int j = 1;j<=n;j++){
			array[j] = sc.nextInt();
		}
		return array;
	}
	static long[] readArrayLong(int n){
		long[] array = new long[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextLong();
		return array;
	}
	static double[] readArrayDouble(int n){
		double[] array = new double[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextDouble();
		return array;
	}
	static int minIndex(int[] array){
		int minValue = Integer.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(long[] array){
		long minValue = Long.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(double[] array){
		double minValue = Double.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static long power(long x, long y){
		if (y == 0)
			return 1;
		if (y%2 == 1)
			return (x*power(x, y-1))%mod;
		return power((x*x)%mod, y/2)%mod;
	}
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String nextLine() {
            String str = "";
            try{
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is

import java.util.*;
import java.io.*;
public class EdB {
	static long[] mods = {1000000007, 998244353, 1000000009};
	static long mod = mods[0];
	public static MyScanner sc;
    public static PrintWriter out;
    static long[][] matrix;
    static int m;
	public static void main(String[] omkar) throws Exception{
		// TODO Auto-generated method stub
 		sc = new MyScanner();
 		PrintWriter out = new PrintWriter(System.out);
 		long n = sc.nextLong();
 		m = sc.nextInt();
 		matrix = new long[m][m];
 		matrix[0][0] = 1;
 		matrix[0][m-1] = 1;
 		for(int j =1;j<m;j++){
 			matrix[j][j-1] = 1;
 		}
 		long[][] newm = power(matrix, n-(long)m);
 		long ans = (2L*newm[0][0]+newm[0][m-1])%mod;
 		out.println(ans);

 		out.close();
 	}
	public static long[][] mul(long[][] m1, long[][] m2){
		long[][] ans = new long[m][m];
		for(int j =0;j<m;j++){
			for(int k = 0;k<m;k++){
				long sum = 0;
				for(int l = 0;l<m;l++){
					sum+=m1[j][l]*m2[l][k];
					sum%=mod;
				}
				ans[j][k] = sum;
			}
		}
		return ans;
	}
	public static long[][] power(long[][] m, long k){
		if (k == 1)
			return m;
		long [][]ks = power(m, k/2);
		if (k%2 == 0)
			return mul(ks, ks);
		else
			return mul(mul(ks, ks), m);
	}
	public static void sort(int[] array){
		ArrayList<Integer> copy = new ArrayList<Integer>();
		for (int i : array)
			copy.add(i);
		Collections.sort(copy);
		for(int i = 0;i<array.length;i++)
			array[i] = copy.get(i);
	}
	static String[] readArrayString(int n){
		String[] array = new String[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.next();
		return array;
	}
	static int[] readArrayInt(int n){
    	int[] array = new int[n];
    	for(int j = 0;j<n;j++)
    		array[j] = sc.nextInt();
    	return array;
    }
	static int[] readArrayInt1(int n){
		int[] array = new int[n+1];
		for(int j = 1;j<=n;j++){
			array[j] = sc.nextInt();
		}
		return array;
	}
	static long[] readArrayLong(int n){
		long[] array = new long[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextLong();
		return array;
	}
	static double[] readArrayDouble(int n){
		double[] array = new double[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextDouble();
		return array;
	}
	static int minIndex(int[] array){
		int minValue = Integer.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(long[] array){
		long minValue = Long.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(double[] array){
		double minValue = Double.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static long power(long x, long y){
		if (y == 0)
			return 1;
		if (y%2 == 1)
			return (x*power(x, y-1))%mod;
		return power((x*x)%mod, y/2)%mod;
	}
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String nextLine() {
            String str = "";
            try{
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is

import java.util.*;

public class Main {
    static int mod = 1_000_000_000;
static long[][] mul(long[][] A, long[][] B) {
    long[][] C = new long[A.length][B[0].length];
    for (int i=0;i<A.length;i++) {
        for (int k=0;k<B.length;k++) {
            for (int j=0;j<B[0].length;j++) {
                C[i][j] = (C[i][j]+A[i][k]*B[k][j]%mod)%mod;
            }
        }
    }
    return C;
}

static long[][] pow(long[][] A, long n) {
    long[][] B = new long[A.length][A.length];
    for (int i=0;i<A.length;i++) {
        B[i][i]=1;
    }
    while (n>0) {
        if ((n&1)==1) {
            B = mul(B, A);
        }
        A = mul(A, A);
        n>>=1;
    }
    return B;
}

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long N = sc.nextLong();
        int M = sc.nextInt();
        long[][] matrix = new long[M][M];
        matrix[0][0] = 1;
        matrix[0][M-1] = 1;
        for (int i=1;i<M;i++) {
            matrix[i][i-1] = 1;
        }

        if (N<M) {
            System.out.println(1);
            return;
        }
        long[][] ans = pow(matrix, N-M+1);
        // System.out.println(Arrays.deepToString(matrix));
        long[][] arr = new long[M][1];
        for (int i=0;i<M;i++) {
            arr[i][0] = 1;
        }
        ans = mul(ans, arr);
        // System.out.println(Arrays.deepToString(ans));
        System.out.println(ans[0][0]);
    }
}

import java.util.*;

public class Main {
    static int mod = 1_000_000_000;
static int[][] mul(int[][] A, int[][] B) {
    int[][] C = new int[A.length][B[0].length];
    for (int i=0;i<A.length;i++) {
        for (int k=0;k<B.length;k++) {
            for (int j=0;j<B[0].length;j++) {
                C[i][j] = (C[i][j]+A[i][k]*B[k][j])%mod;
            }
        }
    }
    return C;
}

static int[][] pow(int[][] A, long n) {
    int[][] B = new int[A.length][A.length];
    for (int i=0;i<A.length;i++) {
        B[i][i]=1;
    }
    while (n>0) {
        if ((n&1)==1) {
            B = mul(B, A);
        }
        A = mul(A, A);
        n>>=1;
    }
    return B;
}

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long N = sc.nextLong();
        int M = sc.nextInt();
        int[][] matrix = new int[M][M];
        matrix[0][0] = 1;
        matrix[0][M-1] = 1;
        for (int i=1;i<M;i++) {
            matrix[i][i-1] = 1;
        }

        if (N<M) {
            System.out.println(1);
            return;
        }
        int[][] ans = pow(matrix, N-M+1);
        int[][] arr = new int[M][1];
        for (int i=0;i<M;i++) {
            arr[i][0] = 1;
        }
        ans = mul(ans, arr);
        System.out.println(ans[0][0]);
    }
}

import java.util.*;

public class Main {
    static int mod = 1_000_000_000;
static long[][] mul(long[][] A, long[][] B) {
    long[][] C = new long[A.length][B[0].length];
    for (int i=0;i<A.length;i++) {
        for (int k=0;k<B.length;k++) {
            for (int j=0;j<B[0].length;j++) {
                C[i][j] = (C[i][j]+A[i][k]*B[k][j])%mod;
            }
        }
    }
    return C;
}

static long[][] pow(long[][] A, long n) {
    long[][] B = new long[A.length][A.length];
    for (int i=0;i<A.length;i++) {
        B[i][i]=1;
    }
    while (n>0) {
        if ((n&1)==1) {
            B = mul(B, A);
        }
        A = mul(A, A);
        n>>=1;
    }
    return B;
}

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long N = sc.nextLong();
        int M = sc.nextInt();
        long[][] matrix = new long[M][M];
        matrix[0][0] = 1;
        matrix[0][M-1] = 1;
        for (int i=1;i<M;i++) {
            matrix[i][i-1] = 1;
        }

        if (N<M) {
            System.out.println(1);
            return;
        }
        long[][] ans = pow(matrix, N-M+1);
        long[][] arr = new long[M][1];
        for (int i=0;i<M;i++) {
            arr[i][0] = 1;
        }
        ans = mul(ans, arr);
        System.out.println(ans[0][0]);
    }
}

import java.util.Scanner;

public class D
{
	static int mod = 1000000007;
	public static void main(String[] args)
	{
		Scanner scan = new Scanner(System.in);
		long n = scan.nextLong();
		int m = scan.nextInt();
		int[][] matrix = new int[m][m];
		matrix[0][0] = 1;
		matrix[m-1][0] = 1;
		for (int i = 1; i < m; i++)
			matrix[i-1][i] = 1;
		int[][] res = fastExpo(matrix, n);
		int[][] init = new int[1][m];
		init[0][0] = 1;
		System.out.println(mult(init, res)[0][0]);
	}

	private static int[][] fastExpo(int[][] matrix, long p)
	{
		if (p == 1)
			return matrix;
		if (p % 2 == 1)
			return mult(matrix, fastExpo(matrix, p-1));
		int[][] half = fastExpo(matrix, p/2);
		return mult(half, half);
	}

	private static int[][] mult(int[][] a, int[][] b)
	{
		int[][] res = new int[a.length][b[0].length];
		for (int i = 0; i < res.length; i++)
		{
			for (int j = 0; j < res[0].length; j++)
			{
				long s = 0;
				for (int k = 0; k < b.length; k++)
					s += (long)a[i][k]*b[k][j];
				res[i][j] = (int)(s % mod);
			}
		}
		return res;
	}
}

import java.util.Scanner;

public class D
{
	static int mod = 1000000007;
	public static void main(String[] args)
	{
		Scanner scan = new Scanner(System.in);
		long n = scan.nextLong();
		int m = scan.nextInt();
		int[][] matrix = new int[m][m];
		matrix[0][0] = 1;
		matrix[m-1][0] = 1;
		for (int i = 1; i < m; i++)
			matrix[i-1][i] = 1;
		int[][] res = fastExpo(matrix, n);
		int[][] init = new int[1][m];
		init[0][0] = 1;
		System.out.println(mult(init, res)[0][0]);
	}

	private static int[][] fastExpo(int[][] matrix, long p)
	{
		if (p == 1)
			return matrix;
		if (p % 2 == 1)
			return mult(matrix, fastExpo(matrix, p-1));
		int[][] half = fastExpo(matrix, p/2);
		return mult(half, half);
	}

	private static int[][] mult(int[][] a, int[][] b)
	{
		int[][] res = new int[a.length][b[0].length];
		for (int i = 0; i < res.length; i++)
		{
			for (int j = 0; j < res[0].length; j++)
			{
				long s = 0;
				for (int k = 0; k < b.length; k++)
					s += a[i][k]*b[k][j];
				res[i][j] = (int)(s % mod);
			}
		}
		return res;
	}
}

import java.util.*;

public class D {

    public static final int MOD = 1000000007;
    public static long[][] multiply_matrix = new long[103][103];

    public static void matrix_multiplication(int m, long[][] final_matrix, long[][] multiply_matrix){
        long[][] mult = new long[m][m];

        for(int i=0; i<m; i++){
            for(int j=0; j<m; j++){
                mult[i][j] = 0;
                for(int k=0; k<m; k++){
                    mult[i][j] += final_matrix[i][k] * multiply_matrix[k][j];
                    if(mult[i][j] > MOD){
                        mult[i][j] -= MOD;
                    }
                }
            }
        }
        for(int i=0; i<m; i++){
            for(int j=0; j<m; j++){
                final_matrix[i][j] = mult[i][j];
            }
        }
    }

    public static void matrix_power(long n, long[][] final_matrix, int m){
        long[][] ans = new long[m][100];
        long[][] b = new long[m][100];

        for(int i=0; i<m; i++){
            for(int j=0; j<m; j++){
                ans[i][j] = multiply_matrix[i][j];
                b[i][j] = multiply_matrix[i][j];
            }
        }
        n--;
        while (n > 0){
            if(n % 2 == 1){
                matrix_multiplication(m, ans, b);
                n--;
            }
            else{
                matrix_multiplication(m, b, b);
                n /= 2;
            }
        }
        for(int i=0; i<m; i++){
            for(int j=0; j<m; j++){
                final_matrix[i][j] = ans[i][j];
            }
        }
    }
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        long n = scan.nextLong();
        int m = scan.nextInt();

        scan.close();

        for(int i=0; i<m; i++){
            for(int j=0; j<m; j++){
                multiply_matrix[i][j] = 0;
            }
        }

        multiply_matrix[0][0] = 1;
        multiply_matrix[0][m-1] = 1;
        for(int i=1; i<m; i++){
            multiply_matrix[i][i-1] = 1;
        }
        if(n < m){
            System.out.println(1);
        }
        else {
            long[][] final_matrix = new long[m+1][100];
            matrix_power(n-m+1, final_matrix, m);
            long ans = 0;
            for(int i=0; i<m; i++){
                ans += final_matrix[0][i];
                if (ans >= MOD){
                    ans -= MOD;
                }
            }
            System.out.println(ans);
        }
    }
}

//created by Whiplash99
import java.io.*;
import java.util.*;
public class F
{
    private static final long MOD=(long)(1e9+7);
    static class Matrix
    {
        long[][] M; int N;
        Matrix(int N){this.N=N; M=new long[N][N];}
        void makeIdentity(){for(int i=0;i<N;i++) M[i][i]=1;}
        void copy(Matrix source)
        {
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    M[i][j]=source.M[i][j];
        }
        void multiply(Matrix B, Matrix C)
        {
            for(int i=0;i<N;i++) Arrays.fill(C.M[i],0);
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    for(int k=0;k<N;k++)
                        C.M[i][j]=add(C.M[i][j],prod(M[i][k],B.M[k][j]));
            copy(C);
        }
        void pow(long b)
        {
            Matrix res=new Matrix(N), store=new Matrix(N);
            res.makeIdentity(); b%=(MOD-1);
            while (b>0)
            {
                if((b&1)==1) res.multiply(this,store);
                this.multiply(this,store);
                b>>=1;
            }
            copy(res);
        }
    }
    private static long add(long a, long b){a+=b; return (a>=MOD)?a-MOD:a;}
    private static long prod(long a, long b){a*=b; return (a>=MOD)?a%MOD:a;}
    public static void main(String[] args) throws IOException
    {
        Reader r=new Reader();

        int i,j;

        long N=r.nextLong();
        int M=r.nextInt();

        if(N<M){ System.out.println(1); System.exit(0);}

        Matrix A=new Matrix(M);
        Matrix P=new Matrix(M);
        Matrix store=new Matrix(M);

        Arrays.fill(A.M[0],1); A.M[0][M-1]=2;
        for(i=1;i<M;i++) P.M[i][i-1]=1; P.M[0][M-1]=P.M[M-1][M-1]=1;

        P.pow(N-M);
        A.multiply(P,store);

        System.out.println(A.M[0][M-1]);
    }
    static class Reader
    {
        final private int BUFFER_SIZE = 1 << 16;private DataInputStream din;private byte[] buffer;private int bufferPointer, bytesRead;
        public Reader(){din=new DataInputStream(System.in);buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public Reader(String file_name) throws IOException{din=new DataInputStream(new FileInputStream(file_name));buffer=new byte[BUFFER_SIZE];bufferPointer=bytesRead=0;
        }public String readLine() throws IOException{byte[] buf=new byte[64];int cnt=0,c;while((c=read())!=-1){if(c=='\n')break;buf[cnt++]=(byte)c;}return new String(buf,0,cnt);
        }public int nextInt() throws IOException{int ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
        }public long nextLong() throws IOException{long ret=0;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c=read();do{ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(neg)return -ret;return ret;
        }public double nextDouble() throws IOException{double ret=0,div=1;byte c=read();while(c<=' ')c=read();boolean neg=(c=='-');if(neg)c = read();do {ret=ret*10+c-'0';}while((c=read())>='0'&&c<='9');if(c=='.')while((c=read())>='0'&&c<='9')ret+=(c-'0')/(div*=10);if(neg)return -ret;return ret;
        }private void fillBuffer() throws IOException{bytesRead=din.read(buffer,bufferPointer=0,BUFFER_SIZE);if(bytesRead==-1)buffer[0]=-1;
        }private byte read() throws IOException{if(bufferPointer==bytesRead)fillBuffer();return buffer[bufferPointer++];
        }public void close() throws IOException{if(din==null) return;din.close();}
    }
}

//created by Whiplash99
import java.io.*;
import java.util.*;
public class F
{
    private static final long MOD=(long)(1e9+7);
    static class Matrix
    {
        long[][] M; int N;
        Matrix(int N){this.N=N; M=new long[N][N];}
        void makeIdentity(){for(int i=0;i<N;i++) M[i][i]=1;}
        void copy(Matrix source)
        {
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    M[i][j]=source.M[i][j];
        }
        void multiply(Matrix B, Matrix C)
        {
            for(int i=0;i<N;i++) Arrays.fill(C.M[i],0);
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    for(int k=0;k<N;k++)
                        C.M[i][j]=(C.M[i][j]+M[i][k]*B.M[k][j]%MOD)%MOD;
            copy(C);
        }
        void pow(long b)
        {
            Matrix res=new Matrix(N), store=new Matrix(N);
            res.makeIdentity(); b%=(MOD-1); //only if MOD is prime.
            while (b>0)
            {
                if((b&1)==1) res.multiply(this,store);
                this.multiply(this,store);
                b>>=1;
            }
            copy(res);
        }
    }
    public static void main(String[] args) throws IOException
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

        int i,j;

        String s[]=br.readLine().trim().split(" ");
        long N=Long.parseLong(s[0]);
        int M=Integer.parseInt(s[1]);

        if(N==1){ System.out.println(1); System.exit(0);}

        Matrix A=new Matrix(M);
        Matrix P=new Matrix(M);
        Matrix store=new Matrix(M);

        Arrays.fill(A.M[0],1); A.M[0][M-1]=2;
        for(i=1;i<M;i++) P.M[i][i-1]=1; P.M[0][M-1]=P.M[M-1][M-1]=1;

        P.pow(N-2);
        A.multiply(P,store);

        System.out.println(A.M[0][M-1]);
    }
}

//created by Whiplash99
import java.io.*;
import java.util.*;
public class F
{
    private static final long MOD=(long)(1e9+7);
    static class Matrix
    {
        long[][] M; int N;
        Matrix(int N){this.N=N; M=new long[N][N];}
        void makeIdentity(){for(int i=0;i<N;i++) M[i][i]=1;}
        void copy(Matrix source)
        {
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    M[i][j]=source.M[i][j];
        }
        void multiply(Matrix B, Matrix C)
        {
            for(int i=0;i<N;i++) Arrays.fill(C.M[i],0);
            for(int i=0;i<N;i++)
                for(int j=0;j<N;j++)
                    for(int k=0;k<N;k++)
                        C.M[i][j]=(C.M[i][j]+M[i][k]*B.M[k][j]%MOD)%MOD;
            copy(C);
        }
        void pow(long b)
        {
            Matrix res=new Matrix(N), store=new Matrix(N);
            res.makeIdentity();
            while (b>0)
            {
                if((b&1)==1) res.multiply(this,store);
                this.multiply(this,store);
                b>>=1;
            }
            copy(res);
        }
    }
    public static void main(String[] args) throws IOException
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

        int i,j;

        String s[]=br.readLine().trim().split(" ");
        long N=Long.parseLong(s[0]);
        int M=Integer.parseInt(s[1]);

        if(N==1){ System.out.println(1); System.exit(0);}

        Matrix A=new Matrix(M);
        Matrix P=new Matrix(M);
        Matrix store=new Matrix(M);

        Arrays.fill(A.M[0],1); A.M[0][M-1]=2;
        for(i=1;i<M;i++) P.M[i][i-1]=1; P.M[0][M-1]=P.M[M-1][M-1]=1;

        P.pow(N-2);
        A.multiply(P,store);

        System.out.println(A.M[0][M-1]);
    }
}

import java.io.*;
import java.util.*;

public class D implements Runnable {
	FastReader scn;
	PrintWriter out;
	String INPUT = "";

	long mod = 1000_000_000 + 7;

	void solve() {
		long n = scn.nextLong();
		int m = scn.nextInt();
		if (n < m) {
			out.println(0);
			return;
		}

		long[][] gen = new long[m][m];
		gen[0][0] = gen[0][m - 1] = 1;
		for(int i = 1; i < m; i++) {
			gen[i][i - 1] = 1;
		}

		long rv = f(n, gen);
		out.println(rv);
	}

	long f(long n, long[][] gen) {
		long[][] rv = f(gen, gen, n);
		return rv[0][0];
	}

	long[][] f(long[][] mat, long[][] gen, long n){
		if(n == 1) {
			return gen;
		}

		long[][] rv = f(mat, gen, n / 2);
		rv = multiply(rv, rv, mod);
		if(n % 2 == 1) {
			rv = multiply(rv, gen, mod);
		}
		return rv;
	}

	long[][] multiply(long[][] a, long[][] b, long mod) {
		if (a[0].length != b.length) {
			return null;
		}

		long[][] rv = new long[a.length][b[0].length];
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < b[0].length; j++) {
				for (int k = 0; k < b.length; k++) {
					rv[i][j] += (a[i][k] * b[k][j]) % mod;
					rv[i][j] %= mod;
				}
			}
		}

		return rv;
	}

	public void run() {
		long time = System.currentTimeMillis();
		boolean oj = System.getProperty("ONLINE_JUDGE") != null;
		out = new PrintWriter(System.out);
		scn = new FastReader(oj);
		solve();
		out.flush();
		if (!oj) {
			System.out.println(Arrays.deepToString(new Object[] { System.currentTimeMillis() - time + " ms" }));
		}
	}

	public static void main(String[] args) {
		new Thread(null, new D(), "1", 1 << 26).start();
	}

	class FastReader {
		InputStream is;

		public FastReader(boolean onlineJudge) {
			is = onlineJudge ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		}

		byte[] inbuf = new byte[1024];
		public int lenbuf = 0, ptrbuf = 0;

		int readByte() {
			if (lenbuf == -1)
				throw new InputMismatchException();
			if (ptrbuf >= lenbuf) {
				ptrbuf = 0;
				try {
					lenbuf = is.read(inbuf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (lenbuf <= 0)
					return -1;
			}
			return inbuf[ptrbuf++];
		}

		boolean isSpaceChar(int c) {
			return !(c >= 33 && c <= 126);
		}

		int skip() {
			int b;
			while ((b = readByte()) != -1 && isSpaceChar(b))
				;
			return b;
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}

		char nextChar() {
			return (char) skip();
		}

		String next() {
			int b = skip();
			StringBuilder sb = new StringBuilder();
			while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
				sb.appendCodePoint(b);
				b = readByte();
			}
			return sb.toString();
		}

		String nextLine() {
			int b = skip();
			StringBuilder sb = new StringBuilder();
			while ((!isSpaceChar(b) || b == ' ')) { // when nextLine, (isSpaceChar(b) && b != ' ')
				sb.appendCodePoint(b);
				b = readByte();
			}
			return sb.toString();
		}

		char[] next(int n) {
			char[] buf = new char[n];
			int b = skip(), p = 0;
			while (p < n && !(isSpaceChar(b))) {
				buf[p++] = (char) b;
				b = readByte();
			}
			return n == p ? buf : Arrays.copyOf(buf, p);
		}

		int nextInt() {
			int num = 0, b;
			boolean minus = false;
			while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
				;
			if (b == '-') {
				minus = true;
				b = readByte();
			}

			while (true) {
				if (b >= '0' && b <= '9') {
					num = num * 10 + (b - '0');
				} else {
					return minus ? -num : num;
				}
				b = readByte();
			}
		}

		long nextLong() {
			long num = 0;
			int b;
			boolean minus = false;
			while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
				;
			if (b == '-') {
				minus = true;
				b = readByte();
			}

			while (true) {
				if (b >= '0' && b <= '9') {
					num = num * 10 + (b - '0');
				} else {
					return minus ? -num : num;
				}
				b = readByte();
			}
		}

		char[][] nextMatrix(int n, int m) {
			char[][] map = new char[n][];
			for (int i = 0; i < n; i++)
				map[i] = next(m);
			return map;
		}

		int[] nextIntArray(int n) {
			int[] a = new int[n];
			for (int i = 0; i < n; i++)
				a[i] = nextInt();
			return a;
		}

		long[] nextLongArray(int n) {
			long[] a = new long[n];
			for (int i = 0; i < n; i++)
				a[i] = nextLong();
			return a;
		}

		int[][] next2DInt(int n, int m) {
			int[][] arr = new int[n][];
			for (int i = 0; i < n; i++) {
				arr[i] = nextIntArray(m);
			}
			return arr;
		}

		long[][] next2DLong(int n, int m) {
			long[][] arr = new long[n][];
			for (int i = 0; i < n; i++) {
				arr[i] = nextLongArray(m);
			}
			return arr;
		}

		int[] shuffle(int[] arr) {
			Random r = new Random();
			for (int i = 1, j; i < arr.length; i++) {
				j = r.nextInt(i);
				arr[i] = arr[i] ^ arr[j];
				arr[j] = arr[i] ^ arr[j];
				arr[i] = arr[i] ^ arr[j];
			}
			return arr;
		}

		int[] uniq(int[] arr) {
			Arrays.sort(arr);
			int[] rv = new int[arr.length];
			int pos = 0;
			rv[pos++] = arr[0];
			for (int i = 1; i < arr.length; i++) {
				if (arr[i] != arr[i - 1]) {
					rv[pos++] = arr[i];
				}
			}
			return Arrays.copyOf(rv, pos);
		}

		int[] reverse(int[] arr) {
			int l = 0, r = arr.length - 1;
			while (l < r) {
				arr[l] = arr[l] ^ arr[r];
				arr[r] = arr[l] ^ arr[r];
				arr[l] = arr[l] ^ arr[r];
				l++;
				r--;
			}
			return arr;
		}

	}
}

import java.io.*;
import java.util.*;

public class D implements Runnable {
	FastReader scn;
	PrintWriter out;
	String INPUT = "1 2";

	void solve() {
		long n = scn.nextLong();
		int m = scn.nextInt();
		if(n < m) {
			out.println(0);
			return;
		}
		init();
		long ans = 0;
		for(int i = 0; i <= m; i++) {
			long rv = ncr(n - i * (m - 1), i);
			if(rv == 0) {
				break;
			}
			ans = (ans + rv) % mod;
		}
		out.println(ans);
	}

	long[] fact = new long[101], ifact = new long[101];
	int mod = 1000_000_000 + 7;

	void init() {
		ifact[0] = fact[0] = 1;
		for(int i = 1; i <= 100; i++) {
			fact[i] = (fact[i - 1] * i) % mod;
			ifact[i] = inv(fact[i], mod);
		}
	}

	long ncr(long N, int r) {
		if(N < r) {
			return 0;
		}
		long rv = 1;
		for(long n = N, i = 0; i < r; i++, n--) {
			rv = (rv * n) % mod;
		}
		rv = (rv * ifact[r]) % mod;

		return rv;
	}

	long inv(long a, long b) {
		return a > 1 ? b - inv(b % a, a) * b / a : 1; // This will not work when (a * b) overflows
	}

	public void run() {
		long time = System.currentTimeMillis();
		boolean oj = System.getProperty("ONLINE_JUDGE") != null;
		out = new PrintWriter(System.out);
		scn = new FastReader(oj);
		solve();
		out.flush();
		if (!oj) {
			System.out.println(Arrays.deepToString(new Object[] { System.currentTimeMillis() - time + " ms" }));
		}
	}

	public static void main(String[] args) {
		new Thread(null, new D(), "1", 1 << 26).start();
	}

	class FastReader {
		InputStream is;

		public FastReader(boolean onlineJudge) {
			is = onlineJudge ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		}

		byte[] inbuf = new byte[1024];
		public int lenbuf = 0, ptrbuf = 0;

		int readByte() {
			if (lenbuf == -1)
				throw new InputMismatchException();
			if (ptrbuf >= lenbuf) {
				ptrbuf = 0;
				try {
					lenbuf = is.read(inbuf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (lenbuf <= 0)
					return -1;
			}
			return inbuf[ptrbuf++];
		}

		boolean isSpaceChar(int c) {
			return !(c >= 33 && c <= 126);
		}

		int skip() {
			int b;
			while ((b = readByte()) != -1 && isSpaceChar(b))
				;
			return b;
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}

		char nextChar() {
			return (char) skip();
		}

		String next() {
			int b = skip();
			StringBuilder sb = new StringBuilder();
			while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
				sb.appendCodePoint(b);
				b = readByte();
			}
			return sb.toString();
		}

		String nextLine() {
			int b = skip();
			StringBuilder sb = new StringBuilder();
			while ((!isSpaceChar(b) || b == ' ')) { // when nextLine, (isSpaceChar(b) && b != ' ')
				sb.appendCodePoint(b);
				b = readByte();
			}
			return sb.toString();
		}

		char[] next(int n) {
			char[] buf = new char[n];
			int b = skip(), p = 0;
			while (p < n && !(isSpaceChar(b))) {
				buf[p++] = (char) b;
				b = readByte();
			}
			return n == p ? buf : Arrays.copyOf(buf, p);
		}

		int nextInt() {
			int num = 0, b;
			boolean minus = false;
			while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
				;
			if (b == '-') {
				minus = true;
				b = readByte();
			}

			while (true) {
				if (b >= '0' && b <= '9') {
					num = num * 10 + (b - '0');
				} else {
					return minus ? -num : num;
				}
				b = readByte();
			}
		}

		long nextLong() {
			long num = 0;
			int b;
			boolean minus = false;
			while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
				;
			if (b == '-') {
				minus = true;
				b = readByte();
			}

			while (true) {
				if (b >= '0' && b <= '9') {
					num = num * 10 + (b - '0');
				} else {
					return minus ? -num : num;
				}
				b = readByte();
			}
		}

		char[][] nextMatrix(int n, int m) {
			char[][] map = new char[n][];
			for (int i = 0; i < n; i++)
				map[i] = next(m);
			return map;
		}

		int[] nextIntArray(int n) {
			int[] a = new int[n];
			for (int i = 0; i < n; i++)
				a[i] = nextInt();
			return a;
		}

		long[] nextLongArray(int n) {
			long[] a = new long[n];
			for (int i = 0; i < n; i++)
				a[i] = nextLong();
			return a;
		}

		int[][] next2DInt(int n, int m) {
			int[][] arr = new int[n][];
			for (int i = 0; i < n; i++) {
				arr[i] = nextIntArray(m);
			}
			return arr;
		}

		long[][] next2DLong(int n, int m) {
			long[][] arr = new long[n][];
			for (int i = 0; i < n; i++) {
				arr[i] = nextLongArray(m);
			}
			return arr;
		}

		int[] shuffle(int[] arr) {
			Random r = new Random();
			for (int i = 1, j; i < arr.length; i++) {
				j = r.nextInt(i);
				arr[i] = arr[i] ^ arr[j];
				arr[j] = arr[i] ^ arr[j];
				arr[i] = arr[i] ^ arr[j];
			}
			return arr;
		}

		int[] uniq(int[] arr) {
			Arrays.sort(arr);
			int[] rv = new int[arr.length];
			int pos = 0;
			rv[pos++] = arr[0];
			for (int i = 1; i < arr.length; i++) {
				if (arr[i] != arr[i - 1]) {
					rv[pos++] = arr[i];
				}
			}
			return Arrays.copyOf(rv, pos);
		}

		int[] reverse(int[] arr) {
			int l = 0, r = arr.length - 1;
			while (l < r) {
				arr[l] = arr[l] ^ arr[r];
				arr[r] = arr[l] ^ arr[r];
				arr[l] = arr[l] ^ arr[r];
				l++;
				r--;
			}
			return arr;
		}

	}
}

import java.util.*;

public class MagicGems
{

	public static void main(String[] args)
	{
		Scanner scan = new Scanner(System.in);
		long n = scan.nextLong();
		int m = scan.nextInt();
		if(n < m) {
			System.out.println(1);
			return;
		}
		long[][] mat = new long[m][m];
		mat[0][0] = 1;
		mat[1][0] = 1;
		for(int i = 1; i < m; i++) mat[i-1][i] = 1;
		mat = matPow(mat, n-m+2, 1_000_000_007);
		System.out.println(mat[0][0]);
	}

	static long[][] matPow(long[][] A, long p, int mod){
		if(p == 1)
			return A;
		if(p % 2 == 1) {
			long[][] B = matPow(A, p-1, mod);
			return multiply(B, A, mod);
		}
		long[][] B = matPow(A, p/2, mod);
		return multiply(B, B, mod);
	}

	static long[][] multiply(long[][] A, long[][] B, int mod){
		long[][] res = new long[A.length][B[0].length];
		if(A[0].length != B.length) System.out.println("Invalid multiplication");
		for(int i = 0; i < A.length; i++) {
			for(int j = 0; j < B[0].length; j++) {
				for(int k = 0; k < B.length; k++) {
					res[i][j] += (A[i][k]*B[k][j])%mod;
					res[i][j] %= mod;
				}
			}
		}
		return res;
	}
}

import java.util.*;

public class Dcode {

    static  int m;
    static  int mod = 1000000007;

    static  long[][] mul(long a[][],long n){
        if(n<=1){
            return a;
        }

        long matrix[][] = new long[m][m];
        for(int i=0;i<m;i++){
            matrix[i][i] = 1;

        }

        while(n>0){
                if((n&1) == 1){
                        matrix = mm(matrix,a);

                }

                    a = mm(a,a);

                        n = n>>1;
        }

         return matrix;

    }

    static long[][] mm(long a[][],long b[][]){
        long c[][] = new long[m][m];

        for(int i=0;i<m;i++){
            for(int j=0;j<m;j++){
                long sum = 0;
                for(int k=0;k<m;k++){
                    sum = (sum + a[i][k]*b[k][j])%mod;
                }

                c[i][j] = sum;
            }
        }

        return c;
    }

    public static  void main(String args[]){

        Scanner s = new Scanner(System.in);
        long n = s.nextLong();
        m = s.nextInt();
        // if(n<m){
        //     System.out.println(1);
        //     return;
        // }
        // if(n==m){
        //     System.out.println(2);
        //     return;
        // }
        long a[][] = new long[m][m];

        a[0][0] = 1;
        a[0][m-1] = 1;
        for(int i=1;i<m;i++){
            a[i][i-1] = 1;
        }

        long ans  = 0;

        long h[][] = mul(a,n-m);

        ans = 2*h[0][0];

        for(int i=1;i<m;i++){
            ans = (ans + h[0][i])%mod;
        }

        System.out.println(ans);

    }
}

/*Author: Satyajeet Singh, Delhi Technological University*/
import java.io.*;
import java.util.*;
import java.text.*;
import java.lang.*;

public class Main {
/*********************************************Constants******************************************/
    static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static long mod=(long)1e9+7;
    static long mod1=998244353;
    static boolean sieve[];
    static ArrayList<Integer> primes;
    static ArrayList<Long> factorial;
    static HashSet<Integer> graph[];
/****************************************Solutions Begins*****************************************/
    static long modder(long x){
        if(x>=mod){
            return x-=mod;
        }
        return x;
    }
    static long[][] matmul(long A[][],long B[][]){
        int n=A.length;
        int p=A[0].length;
        int m=B[0].length;
        long ans[][]=new long[n][m];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                for(int k=0;k<p;k++){
                    ans[i][j]=(ans[i][j]%mod+(A[i][k]%mod)*(B[k][j]%mod))%mod;
                    ans[i][j]=ans[i][j]%mod;
                }
            }
        }
        return ans;
    }
    static long[][] matexpo(long A[][],long exp){
        if(exp==1){
            return A;
        }
        long B[][]=matexpo(A,exp/2);
        if(exp%2==0){
            return matmul(B,B);
        }
        else{
            return matmul(matmul(B,B),A);
        }
    }
    public static void main (String[] args) throws Exception {
        String st[]=br.readLine().split(" ");
        long n=Long.parseLong(st[0])-1;
        int m=Integer.parseInt(st[1]);
        if(m>n){
            out.println(1);
            out.flush();
            return ;
        }
        long mat[][]=new long[m][m];
        long F[][]=new long[m][1];

        for(int i=0;i<m-1;i++){
            mat[i+1][i]=1;
            F[i][0]=1;
        }
        F[m-1][0]=2;
        mat[m-1][m-1]=1;
        mat[0][m-1]=1;
        long T[][]=matexpo(mat,n-1);
        long A[][]=matmul(T,F);
      //  debug(A);
        out.println(A[0][0]);
/****************************************Solutions Ends**************************************************/
        out.flush();
        out.close();
    }
/****************************************Template Begins************************************************/
/***************************************Precision Printing**********************************************/
    static void printPrecision(double d){
        DecimalFormat ft = new DecimalFormat("0.000000");
        out.println(ft.format(d));
    }
/******************************************Graph*********************************************************/
    static void Makegraph(int n){
        graph=new HashSet[n];
        for(int i=0;i<n;i++){
            graph[i]=new HashSet<>();
        }
    }
    static void addEdge(int a,int b){
        graph[a].add(b);
    }

/*********************************************PAIR********************************************************/
    static class PairComp implements Comparator<Pair>{
        public int compare(Pair p1,Pair p2){
            if(p1.u>p2.u){
                return 1;
            }
            else if(p1.u<p2.u){
                return -1;
            }
            else{
                return p1.v-p2.v;
            }
        }
    }
    static class Pair implements Comparable<Pair> {
        int u;
        int v;
        int index=-1;
        public Pair(int u, int v) {
            this.u = u;
            this.v = v;
        }

        public int hashCode() {
            int hu = (int) (u ^ (u >>> 32));
            int hv = (int) (v ^ (v >>> 32));
            return 31 * hu + hv;
        }

        public boolean equals(Object o) {
            Pair other = (Pair) o;
            return u == other.u && v == other.v;
        }

        public int compareTo(Pair other) {
            if(index!=other.index)
                return Long.compare(index, other.index);
            return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
        }

        public String toString() {
            return "[u=" + u + ", v=" + v + "]";
        }
    }

    static class PairCompL implements Comparator<Pairl>{
        public int compare(Pairl p1,Pairl p2){
            if(p1.u>p2.u){
                return 1;
            }
            else if(p1.u<p2.u){
                return -1;
            }
            else{
                return 0;
            }
        }
    }
    static class Pairl implements Comparable<Pair> {
            long u;
            long v;
            int index=-1;
            public Pairl(long u, long v) {
                this.u = u;
                this.v = v;
            }

            public int hashCode() {
                int hu = (int) (u ^ (u >>> 32));
                int hv = (int) (v ^ (v >>> 32));
                return 31 * hu + hv;
            }

            public boolean equals(Object o) {
                Pair other = (Pair) o;
                return u == other.u && v == other.v;
            }

            public int compareTo(Pair other) {
                if(index!=other.index)
                    return Long.compare(index, other.index);
                return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
            }

            public String toString() {
                return "[u=" + u + ", v=" + v + "]";
            }
        }
/*****************************************DEBUG***********************************************************/
    public static void debug(Object... o) {
        System.out.println(Arrays.deepToString(o));
    }
/************************************MODULAR EXPONENTIATION***********************************************/
    static long modulo(long a,long b,long c) {
        long x=1;
        long y=a;
        while(b > 0){
            if(b%2 == 1){
                x=(x*y)%c;
            }
            y = (y*y)%c; // squaring the base
            b /= 2;
        }
        return  x%c;
    }
/********************************************GCD**********************************************************/
    static long gcd(long x, long y)
    {
        if(x==0)
            return y;
        if(y==0)
            return x;
        long r=0, a, b;
        a = (x > y) ? x : y; // a is greater number
        b = (x < y) ? x : y; // b is smaller number
        r = b;
        while(a % b != 0)
        {
            r = a % b;
            a = b;
            b = r;
        }
        return r;
    }
/******************************************SIEVE**********************************************************/
    static void sieveMake(int n){
        sieve=new boolean[n];
        Arrays.fill(sieve,true);
        sieve[0]=false;
        sieve[1]=false;
        for(int i=2;i*i<n;i++){
            if(sieve[i]){
                for(int j=i*i;j<n;j+=i){
                    sieve[j]=false;
                }
            }
        }
        primes=new ArrayList<Integer>();
        for(int i=0;i<n;i++){
            if(sieve[i]){
                primes.add(i);
            }
        }
    }
/********************************************End***********************************************************/
}

/*Author: Satyajeet Singh, Delhi Technological University*/
import java.io.*;
import java.util.*;
import java.text.*;
import java.lang.*;

public class Main {
/*********************************************Constants******************************************/
    static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static long mod=(long)1e9+7;
    static long mod1=998244353;
    static boolean sieve[];
    static ArrayList<Integer> primes;
    static ArrayList<Long> factorial;
    static HashSet<Integer> graph[];
/****************************************Solutions Begins*****************************************/
    static long modder(long x){
        if(x>=mod){
            return x-=mod;
        }
        return x;
    }
    static long[][] matmul(long A[][],long B[][]){
        int n=A.length;
        int p=A[0].length;
        int m=B[0].length;
        long ans[][]=new long[n][m];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                for(int k=0;k<p;k++){
                    ans[i][j]=(ans[i][j]%mod+(A[i][k]%mod)*(B[k][j]%mod))%mod;
                    ans[i][j]=ans[i][j]%mod;
                }
            }
        }
        return ans;
    }
    static long[][] matexpo(long A[][],long exp){
        if(exp==1){
            return A;
        }
        long B[][]=matexpo(A,exp/2);
        if(exp%2==0){
            return matmul(B,B);
        }
        else{
            return matmul(matmul(B,B),A);
        }
    }
    public static void main (String[] args) throws Exception {
        String st[]=br.readLine().split(" ");
        long n=Long.parseLong(st[0]);
        int m=Integer.parseInt(st[1]);
        if(m>n){
            out.println(1);
            out.flush();
            return ;
        }
        long mat[][]=new long[m][m];
        long F[][]=new long[m][1];

        for(int i=0;i<m-1;i++){
            mat[i+1][i]=1;
            F[i][0]=1;
        }
        F[m-1][0]=2;
        mat[m-1][m-1]=1;
        mat[0][m-1]=1;
        long T[][]=matexpo(mat,n-1);
        long A[][]=matmul(T,F);
        out.println(A[0][0]);
/****************************************Solutions Ends**************************************************/
        out.flush();
        out.close();
    }
/****************************************Template Begins************************************************/
/***************************************Precision Printing**********************************************/
    static void printPrecision(double d){
        DecimalFormat ft = new DecimalFormat("0.000000");
        out.println(ft.format(d));
    }
/******************************************Graph*********************************************************/
    static void Makegraph(int n){
        graph=new HashSet[n];
        for(int i=0;i<n;i++){
            graph[i]=new HashSet<>();
        }
    }
    static void addEdge(int a,int b){
        graph[a].add(b);
    }

/*********************************************PAIR********************************************************/
    static class PairComp implements Comparator<Pair>{
        public int compare(Pair p1,Pair p2){
            if(p1.u>p2.u){
                return 1;
            }
            else if(p1.u<p2.u){
                return -1;
            }
            else{
                return p1.v-p2.v;
            }
        }
    }
    static class Pair implements Comparable<Pair> {
        int u;
        int v;
        int index=-1;
        public Pair(int u, int v) {
            this.u = u;
            this.v = v;
        }

        public int hashCode() {
            int hu = (int) (u ^ (u >>> 32));
            int hv = (int) (v ^ (v >>> 32));
            return 31 * hu + hv;
        }

        public boolean equals(Object o) {
            Pair other = (Pair) o;
            return u == other.u && v == other.v;
        }

        public int compareTo(Pair other) {
            if(index!=other.index)
                return Long.compare(index, other.index);
            return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
        }

        public String toString() {
            return "[u=" + u + ", v=" + v + "]";
        }
    }

    static class PairCompL implements Comparator<Pairl>{
        public int compare(Pairl p1,Pairl p2){
            if(p1.u>p2.u){
                return 1;
            }
            else if(p1.u<p2.u){
                return -1;
            }
            else{
                return 0;
            }
        }
    }
    static class Pairl implements Comparable<Pair> {
            long u;
            long v;
            int index=-1;
            public Pairl(long u, long v) {
                this.u = u;
                this.v = v;
            }

            public int hashCode() {
                int hu = (int) (u ^ (u >>> 32));
                int hv = (int) (v ^ (v >>> 32));
                return 31 * hu + hv;
            }

            public boolean equals(Object o) {
                Pair other = (Pair) o;
                return u == other.u && v == other.v;
            }

            public int compareTo(Pair other) {
                if(index!=other.index)
                    return Long.compare(index, other.index);
                return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
            }

            public String toString() {
                return "[u=" + u + ", v=" + v + "]";
            }
        }
/*****************************************DEBUG***********************************************************/
    public static void debug(Object... o) {
        System.out.println(Arrays.deepToString(o));
    }
/************************************MODULAR EXPONENTIATION***********************************************/
    static long modulo(long a,long b,long c) {
        long x=1;
        long y=a;
        while(b > 0){
            if(b%2 == 1){
                x=(x*y)%c;
            }
            y = (y*y)%c; // squaring the base
            b /= 2;
        }
        return  x%c;
    }
/********************************************GCD**********************************************************/
    static long gcd(long x, long y)
    {
        if(x==0)
            return y;
        if(y==0)
            return x;
        long r=0, a, b;
        a = (x > y) ? x : y; // a is greater number
        b = (x < y) ? x : y; // b is smaller number
        r = b;
        while(a % b != 0)
        {
            r = a % b;
            a = b;
            b = r;
        }
        return r;
    }
/******************************************SIEVE**********************************************************/
    static void sieveMake(int n){
        sieve=new boolean[n];
        Arrays.fill(sieve,true);
        sieve[0]=false;
        sieve[1]=false;
        for(int i=2;i*i<n;i++){
            if(sieve[i]){
                for(int j=i*i;j<n;j+=i){
                    sieve[j]=false;
                }
            }
        }
        primes=new ArrayList<Integer>();
        for(int i=0;i<n;i++){
            if(sieve[i]){
                primes.add(i);
            }
        }
    }
/********************************************End***********************************************************/
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author beginner1010
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        final int mod = (int) 1e9 + 7;

        long[][] mul(long[][] A, long[][] B) {
            int a = A.length;
            int b = B.length;
            int c = B[0].length;
            long[][] C = new long[a][c];
            for (int i = 0; i < a; i++) {
                for (int k = 0; k < b; k++) {
                    for (int j = 0; j < c; j++) {
                        C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
                    }
                }
            }
            return C;
        }

        long[][] fastPow(long[][] graph, long p) {
            if (p == 0) {
                int n = graph.length;
                long[][] I = new long[n][n];
                for (int i = 0; i < n; i++) {
                    I[i][i] = 1;
                }
                return I;
            }
            if (p % 2 == 1) {
                return mul(graph, fastPow(graph, p - 1));
            } else {
                long[][] aux = fastPow(graph, p >> 1);
                return mul(aux, aux);
            }
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long N = in.nextLong();
            int M = in.nextInt();

            long[][] graph = new long[M][M];
            for (int i = 1; i < M; i++) {
                graph[i][i - 1] = 1;
                graph[i - 1][i] = 1;
            }
            graph[0][0] = 1;
            graph[0][M - 1] = 1;

            long[][] ways = fastPow(graph, N);

            long[][] base = new long[M][1];
            base[0][0] = 1;
            long[][] ans = mul(ways, base);

            out.println(ans[0][0]);
        }

    }

    static class InputReader {
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputStream stream;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        private boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        private int read() {
            if (numChars == -1)
                throw new InputMismatchException();
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isWhitespace(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isWhitespace(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isWhitespace(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isWhitespace(c));
            return res * sgn;
        }

    }
}

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

public class q5 {

	 static long power(long x, long y, long p)
	    {
	        // Initialize result
	        long res = 1;

	        // Update x if it is more
	        // than or equal to p
	        x = x % p;

	        while (y > 0)
	        {
	            // If y is odd, multiply x
	            // with result
	            if((y & 1)==1)
	                res = (res * x) % p;

	            // y must be even now
	            // y = y / 2
	            y = y >> 1;
	            x = (x * x) % p;
	        }
	        return res;
	    }

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		// Editorial implementation for practice
		Reader.init(System.in);
		StringBuffer output=new StringBuffer("");
		PrintWriter out=new PrintWriter(System.out);
		long mod=1000000007;
//		int x1=Reader.nextInt();
//		int y1=Reader.nextInt();
//		int x2=Reader.nextInt();
//		int y2=Reader.nextInt();
//		int n=Reader.nextInt();
//		String s=Reader.next();
//		int diffx=x2-x1;
//		int diffy=y2-y1;
//		int[][] cng=new int[n][2];
//		int sum1=0,sum2=0;
//		for(int i=0;i<n;i++) {
//			if(s.charAt(i)=='U') {
//				sum2+=1;
//			}
//			else if(s.charAt(i)=='D') {
//				sum2-=1;
//			}
//			else if(s.charAt(i)=='L') {
//				sum1-=1;
//			}
//			else sum1+=1;
//			cng[i][0]=sum1;cng[i][1]=sum2;
//		}
//		long ans=Long.MAX_VALUE;
//		for(int i=0;i<n;i++) {
//
//		}
//		if(ans==Long.MAX_VALUE) {
//			ans=-1;
//		}
//		output.append(ans);
		long n=Reader.nextLong();
		long m=Reader.nextLong();
		long ans=0;
		if(m==1) {
			ans=q5.power(2, n, mod);
		}
		else {
			long c=n/m;
			ans=q5.power(2, c, mod)+1;
			ans%=mod;
		}
		output.append(ans);
		out.write(output.toString());
		out.flush();

	}
}

class DisJoint {
	int[] arr;
	int[] parent;
	int[] rank;
	DisJoint(int n){
		arr=new int[n+1];
		parent=new int[n+1];
		rank=new int[n+1];
		for(int i=1;i<=n;i++) {
			arr[i]=i;
			parent[i]=i;
			rank[i]=0;
		}
	}

	int find(int value) {
		int par=parent[value];
		if(par==value)
			return par;
		parent[value]=find(par);
		return parent[value];
	}

	void union(int data1,int data2) {
		int parent1=find(data1);
		int parent2=find(data2);
		if(parent1!=parent2) {
			if(rank[parent1]>=rank[parent2]) {
				parent[parent2]=parent1;
				if(rank[parent1]==rank[parent2])
					rank[parent1]++;
			}
			else {
				parent[parent1]=parent2;
			}
		}

	}
}

 class Reader {
	    static BufferedReader reader;
	    static StringTokenizer tokenizer;

	    /** call this method to initialize reader for InputStream */
	    static void init(InputStream input) {
	        reader = new BufferedReader(
	                     new InputStreamReader(input) );
	        tokenizer = new StringTokenizer("");
	    }

	    /** get next word */
	    static String nextLine() throws IOException{
	    	return reader.readLine();
	    }
	    static String next() throws IOException {
	        while ( ! tokenizer.hasMoreTokens() ) {
	            //TODO add check for eof if necessary
	            tokenizer = new StringTokenizer(
	                   reader.readLine() );
	        }
	        return tokenizer.nextToken();
	    }

	    static int nextInt() throws IOException {
	        return Integer.parseInt( next() );
	    }
	    static long nextLong() throws IOException {
	        return Long.parseLong( next() );
	    }
	    static double nextDouble() throws IOException {
	        return Double.parseDouble( next() );
	    }
	}

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

public class q5 {

	 static long power(long x, long y, long p)
	    {
	        // Initialize result
	        long res = 1;

	        // Update x if it is more
	        // than or equal to p
	        x = x % p;

	        while (y > 0)
	        {
	            // If y is odd, multiply x
	            // with result
	            if((y & 1)==1)
	                res = (res * x) % p;

	            // y must be even now
	            // y = y / 2
	            y = y >> 1;
	            x = (x * x) % p;
	        }
	        return res;
	    }

	 static long nCrModpDP(long n, long r, long p)
	 {
	     // The array C is going to store last row of
	     // pascal triangle at the end. And last entry
	     // of last row is nCr
	     long[] C=new long[(int)r+1];

	     C[0] = 1; // Top row of Pascal Triangle

	     // One by constructs remaining rows of Pascal
	     // Triangle from top to bottom
	     for (int i = 1; i <= n; i++)
	     {
	         // Fill entries of current row using previous
	         // row values
	         for (int j = (int)Math.min(i, r); j > 0; j--)

	             // nCj = (n-1)Cj + (n-1)C(j-1);
	             C[j] = (C[j] + C[j-1])%p;
	     }
	     return C[(int)r];
	 }

	 // Lucas Theorem based function that returns nCr % p
	 // This function works like decimal to binary conversion
	 // recursive function. First we compute last digits of
	 // n and r in base p, then recur for remaining digits
	 static long nCrModpLucas(long n, long r, long p)
	 {
	 // Base case
	 if (r==0)
	     return 1;

	 // Compute last digits of n and r in base p
	 long ni = n%p;
	 long ri = r%p;

	 // Compute result for last digits computed above, and
	 // for remaining digits. Multiply the two results and
	 // compute the result of multiplication in modulo p.
	 return (nCrModpLucas(n/p, r/p, p) * // Last digits of n and r
	         nCrModpDP(ni, ri, p)) % p; // Remaining digits
	 }

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		// Editorial implementation for practice
		Reader.init(System.in);
		StringBuffer output=new StringBuffer("");
		PrintWriter out=new PrintWriter(System.out);
		long mod=1000000007;
//		int x1=Reader.nextInt();
//		int y1=Reader.nextInt();
//		int x2=Reader.nextInt();
//		int y2=Reader.nextInt();
//		int n=Reader.nextInt();
//		String s=Reader.next();
//		int diffx=x2-x1;
//		int diffy=y2-y1;
//		int[][] cng=new int[n][2];
//		int sum1=0,sum2=0;
//		for(int i=0;i<n;i++) {
//			if(s.charAt(i)=='U') {
//				sum2+=1;
//			}
//			else if(s.charAt(i)=='D') {
//				sum2-=1;
//			}
//			else if(s.charAt(i)=='L') {
//				sum1-=1;
//			}
//			else sum1+=1;
//			cng[i][0]=sum1;cng[i][1]=sum2;
//		}
//		long ans=Long.MAX_VALUE;
//		for(int i=0;i<n;i++) {
//
//		}
//		if(ans==Long.MAX_VALUE) {
//			ans=-1;
//		}
//		output.append(ans);
		long n=Reader.nextLong();
		long m=Reader.nextLong();
		long ans=0;
		if(m==1) {
			ans=q5.power(2, n, mod);
		}
		else {
			ans=q5.power(2, n-m, mod)+1;

		}
		output.append(ans);
		out.write(output.toString());
		out.flush();

	}
}

class DisJoint {
	int[] arr;
	int[] parent;
	int[] rank;
	DisJoint(int n){
		arr=new int[n+1];
		parent=new int[n+1];
		rank=new int[n+1];
		for(int i=1;i<=n;i++) {
			arr[i]=i;
			parent[i]=i;
			rank[i]=0;
		}
	}

	int find(int value) {
		int par=parent[value];
		if(par==value)
			return par;
		parent[value]=find(par);
		return parent[value];
	}

	void union(int data1,int data2) {
		int parent1=find(data1);
		int parent2=find(data2);
		if(parent1!=parent2) {
			if(rank[parent1]>=rank[parent2]) {
				parent[parent2]=parent1;
				if(rank[parent1]==rank[parent2])
					rank[parent1]++;
			}
			else {
				parent[parent1]=parent2;
			}
		}

	}
}

 class Reader {
	    static BufferedReader reader;
	    static StringTokenizer tokenizer;

	    /** call this method to initialize reader for InputStream */
	    static void init(InputStream input) {
	        reader = new BufferedReader(
	                     new InputStreamReader(input) );
	        tokenizer = new StringTokenizer("");
	    }

	    /** get next word */
	    static String nextLine() throws IOException{
	    	return reader.readLine();
	    }
	    static String next() throws IOException {
	        while ( ! tokenizer.hasMoreTokens() ) {
	            //TODO add check for eof if necessary
	            tokenizer = new StringTokenizer(
	                   reader.readLine() );
	        }
	        return tokenizer.nextToken();
	    }

	    static int nextInt() throws IOException {
	        return Integer.parseInt( next() );
	    }
	    static long nextLong() throws IOException {
	        return Long.parseLong( next() );
	    }
	    static double nextDouble() throws IOException {
	        return Double.parseDouble( next() );
	    }
	}

import java.io.*;
import java.util.*;

public class D implements Runnable {
	public static void main (String[] args) {new Thread(null, new D(), "_cf", 1 << 28).start();}

	long MOD = (long)1e9+7;
	long INV = 500000004;

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		long N = fs.nextLong(), M = fs.nextLong();

		long goFor = N/M;
		long have = mult(N, goFor);
		long sub = mult(summation(goFor), M);
		long ret = sub(have, sub);
		ret = (ret + (goFor%MOD) ) % MOD;
		long res = (ret+1)%MOD;
		out.println(res);
		out.close();
	}

	long sub(long a, long b) {
		a %= MOD;
		b %= MOD;
		a -= b;
		while(a < 0) a += MOD;
		a %= MOD;
		return a;
	}

	long mult(long a, long b) {
		a %= MOD; b %= MOD;
		a *= b;
		a %= MOD;
		return a;
	}

	long summation(long n) {
		long it = mult(n, n+1);
		return mult(it, INV);
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) throws FileNotFoundException {
			in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DMagicGems solver = new DMagicGems();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems {
        private int MOD = (int) 1e9 + 7;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long n = in.nextLong();
            int m = in.nextInt();

            long[][] M = new long[m][m];
            M[0][0] = 1;
            M[0][m - 1] = 1;
            for (int i = 1; i < m; i++) {
                M[i][i - 1] = 1;
            }
            Matrix MM = new Matrix(M);
            Matrix.mod = MOD;
            MM = MM.fastPower(n - m + 1);
            long x_n = MM.data[0][0] + MM.data[0][1] % MOD;
            out.println(x_n);
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }

    static class Matrix {
        public static long mod = Long.MAX_VALUE;
        public final long[][] data;
        public final int rowCount;
        public final int columnCount;

        public Matrix(int rowCount, int columnCount) {
            this.rowCount = rowCount;
            this.columnCount = columnCount;
            this.data = new long[rowCount][columnCount];
        }

        public Matrix(long[][] data) {
            this.rowCount = data.length;
            this.columnCount = data[0].length;
            this.data = data;
        }

        public static Matrix multiply(Matrix first, Matrix second) {
            Matrix result = new Matrix(first.rowCount, second.columnCount);
            for (int i = 0; i < first.rowCount; i++) {
                for (int j = 0; j < second.rowCount; j++) {
                    for (int k = 0; k < second.columnCount; k++) {
                        result.data[i][k] = (result.data[i][k] + first.data[i][j] * second.data[j][k]) % mod;
                    }
                }
            }
            return result;
        }

        public static Matrix fastMultiply(Matrix first, Matrix second) {
            Matrix result = new Matrix(first.rowCount, second.columnCount);
            for (int i = 0; i < first.rowCount; i++) {
                for (int j = 0; j < second.rowCount; j++) {
                    for (int k = 0; k < second.columnCount; k++) {
                        result.data[i][k] += first.data[i][j] * second.data[j][k];
                    }
                }
            }
            for (int i = 0; i < first.rowCount; i++) {
                for (int j = 0; j < second.columnCount; j++) {
                    result.data[i][j] %= mod;
                }
            }
            return result;
        }

        public static Matrix identityMatrix(int size) {
            Matrix result = new Matrix(size, size);
            for (int i = 0; i < size; i++) {
                result.data[i][i] = 1;
            }
            return result;
        }

        public Matrix power(long exponent) {
            if (exponent == 0) {
                return identityMatrix(rowCount);
            }
            if (exponent == 1) {
                return this;
            }
            Matrix result = power(exponent >> 1);
            result = multiply(result, result);
            if ((exponent & 1) == 1) {
                result = multiply(result, this);
            }
            return result;
        }

        public Matrix fastPower(long exponent) {
            if (exponent == 0) {
                return identityMatrix(rowCount);
            }
            if (exponent == 1) {
                return this;
            }
            Matrix result = power(exponent >> 1);
            result = fastMultiply(result, result);
            if ((exponent & 1) == 1) {
                result = fastMultiply(result, this);
            }
            return result;
        }

    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        DMagicGems solver = new DMagicGems();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicGems {
        private int MOD = (int) 1e9 + 7;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long n = in.nextLong();
            int m = in.nextInt();

            long[][] M = new long[m][m];
            M[0][0] = 1;
            M[0][m - 1] = 1;
            for (int i = 1; i < m; i++) {
                M[i][i - 1] = 1;
            }
            Matrix MM = new Matrix(M);
            Matrix.mod = MOD;
//        out.println(Arrays.deepToString(MM.data));

            MM = MM.power(n - m + 1);
//        out.println(Arrays.deepToString(MM.data));

            long x_n = 0;
            for (int i = 0; i < m; i++) {
                x_n = x_n + MM.data[0][i] % MOD;
            }
            out.println(x_n);
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }

    static class Matrix {
        public static long mod = Long.MAX_VALUE;
        public final long[][] data;
        public final int rowCount;
        public final int columnCount;

        public Matrix(int rowCount, int columnCount) {
            this.rowCount = rowCount;
            this.columnCount = columnCount;
            this.data = new long[rowCount][columnCount];
        }

        public Matrix(long[][] data) {
            this.rowCount = data.length;
            this.columnCount = data[0].length;
            this.data = data;
        }

        public static Matrix multiply(Matrix first, Matrix second) {
            Matrix result = new Matrix(first.rowCount, second.columnCount);
            for (int i = 0; i < first.rowCount; i++) {
                for (int j = 0; j < second.rowCount; j++) {
                    for (int k = 0; k < second.columnCount; k++) {
                        result.data[i][k] = (result.data[i][k] + first.data[i][j] * second.data[j][k]) % mod;
                    }
                }
            }
            return result;
        }

        public static Matrix identityMatrix(int size) {
            Matrix result = new Matrix(size, size);
            for (int i = 0; i < size; i++) {
                result.data[i][i] = 1;
            }
            return result;
        }

        public Matrix power(long exponent) {
            if (exponent == 0) {
                return identityMatrix(rowCount);
            }
            if (exponent == 1) {
                return this;
            }
            Matrix result = power(exponent >> 1);
            result = multiply(result, result);
            if ((exponent & 1) == 1) {
                result = multiply(result, this);
            }
            return result;
        }

    }
}

import java.io.*;
import java.util.*;

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

	public static void main(String[] args) {
		FastScanner sc = new FastScanner();
		PrintWriter pw = new PrintWriter(System.out);
		long N = sc.nl();
		int M = sc.ni();
		//Relationship is g(i)=g(i-1)+g(i-M)

		long[][] mat = new long[M][M];
		mat[0][0] = 1;
		mat[0][M-1] = 1;
		for (int i = 1; i < M; i++) {
			mat[i][i-1] = 1;
		}

		Matrix MATRIX = new Matrix(mat,MOD);
		if (N < M) {
			pw.println(1);
		} else {
			long[][] pow = MATRIX.matpower(MATRIX.matrix,N-M+1);
			//g(m-1), g(m-2),...,g(0) are all equal to 1.
			long ans = 0;
			for (int i = 0; i < M; i++) {
				ans += pow[0][i];
				ans %= MOD;
			}
			pw.println(ans);
		}
		pw.close();
 	}

	//Useful in matrix multiplacation for linear relationships
	static class Matrix {
		public long[][] matrix;
		public long MOD;
		public int M;

		public Matrix(long[][] matrix, long MOD) {
			this.matrix = matrix;
			this.MOD = MOD;
			M = matrix.length;
		}

		public long[][] matmul(long[][] a, long[][] b) {
	        long[][] ans = new long[M][M];
	        for (int i = 0; i < M; i++) {
	            for (int j = 0; j < M; j++) {
	                for (int k = 0; k < M; k++) {
	                    ans[i][j] += a[i][k]*b[k][j];
	                    ans[i][j] %= MOD;
	                }
	            }
	        }
	        return ans;
		}

		public long[][] matpower(long[][] mat, long pow) {
			if (pow == 1) {
				return mat;
			}
			matpower(mat,pow/2);
			mat = matmul(mat,mat);
			if (pow%2 == 1) {
				mat = matmul(mat,matrix);
			}
			return mat;
		}
	}

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException  e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int ni() {
            return Integer.parseInt(next());
        }

        long nl() {
            return Long.parseLong(next());
        }

        double nd() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Rustam Musin (t.me/musin_acm)
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        DMagicheskieKamni solver = new DMagicheskieKamni();
        solver.solve(1, in, out);
        out.close();
    }

    static class DMagicheskieKamni {
        int mod = (int) 1e9 + 7;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            long n = in.readLong();
            int m = in.readInt();

            int[][] first = new int[m + 2][m + 2];
            for (int i = 0; i <= m; i++) {
                first[i][m + 1] = 1;
                first[i][(i + 1) % (m + 1)] = 1;
            }
            first[m][m] = 1;
            first[m + 1][m + 1] = 1;

            int[][] multed = pow(first, n);
            int answer = multed[0][m + 1];
            out.print(answer);
        }

        int add(int a, int b) {
            a += b;
            if (a >= mod) {
                a -= mod;
            }
            return a;
        }

        int mul(int a, int b) {
            long c = a * (long) b;
            return (int) (c % mod);
        }

        int[][] mul(int[][] a, int[][] b) {
            int n = a.length;
            int m = b[0].length;
            int[][] c = new int[n][m];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    for (int k = 0; k < a[i].length; k++) {
                        c[i][j] = add(c[i][j], mul(a[i][k], b[k][j]));
                    }
                }
            }
            return c;
        }

        int[][] ones(int n) {
            int[][] a = new int[n][n];
            for (int i = 0; i < n; i++) {
                a[i][i] = 1;
            }
            return a;
        }

        int[][] pow(int[][] a, long p) {
            if (p == 0) {
                return ones(a.length);
            }
            int[][] res = pow(a, p / 2);
            res = mul(res, res);
            if (p % 2 == 1) {
                res = mul(res, a);
            }
            return res;
        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void close() {
            writer.close();
        }

        public void print(int i) {
            writer.print(i);
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int readInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long readLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }
}

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MOD = 1000000007;

    // After writing solution, quick scan for:
    //   array out of bounds
    //   special cases e.g. n=1?
    //
    // Big numbers arithmetic bugs:
    //   int overflow
    //   sorting, or taking max, after MOD
    void solve() throws IOException {
        long[] NM = rll(2);
        long N = NM[0];
        int M = (int) NM[1];
        pw.println(helper(N, M));
    }

    Map<Long, Long> memo = new HashMap<>();
    long helper(long N, int M) {
        if (N == M) return 2;
        if (N < M) return 1;
        if (N < 0) return 0;
        if (memo.containsKey(N)) return memo.get(N);
        long ans = 0;
        long mid = N / 2;
        long left = helper(mid, M);  // all in left
        long right = helper(N - mid, M);  // all in right
        ans = (ans + left * right) % MOD;
        // middle two are 0s
        for (int i = 1; i <= M-1; i++) {  // i is how many are in left half
            int j = M-i;
            long l = helper(mid - i, M);
            long r = helper(N-mid - j, M);
            ans = (ans + l * r) % MOD;
        }
        memo.put(N, ans);
        return ans;
    }

    // Template code below

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.solve();
        m.close();
    }

    void close() throws IOException {
        pw.flush();
        pw.close();
        br.close();
    }

    int ri() throws IOException {
        return Integer.parseInt(br.readLine().trim());
    }

    long rl() throws IOException {
        return Long.parseLong(br.readLine().trim());
    }

    int[] ril(int n) throws IOException {
        int[] nums = new int[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            int x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    long[] rll(int n) throws IOException {
        long[] nums = new long[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            long x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    int[] rkil() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return ril(x);
    }

    long[] rkll() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return rll(x);
    }

    char[] rs() throws IOException {
        return br.readLine().toCharArray();
    }

    void sort(int[] A) {
        Random r = new Random();
        for (int i = A.length-1; i > 0; i--) {
            int j = r.nextInt(i+1);
            int temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }
        Arrays.sort(A);
    }
}

import java.io.*;
import java.util.*;

public class CFD {

    BufferedReader br;
    PrintWriter out;
    StringTokenizer st;
    boolean eof;
    private static long MOD = 1000L * 1000L * 1000L + 7;
    private static final int[] dx = {0, -1, 0, 1};
    private static final int[] dy = {1, 0, -1, 0};
    private static final String yes = "Yes";
    private static final String no = "No";

    long n;
    int m;
    void solve() throws IOException {
        n = nextLong();
        m = nextInt();
        n--;
        long[][] mat = new long[m][m];
        mat[0][0] = 1;
        mat[0][m - 1] = 1;
        for (int i = 1; i < m; i++) {
            mat[i][i - 1] = 1;
        }

        long[][] powN = matrixPow(mat, n);
        long res = 0;
        for (int i = 0; i < m; i++) {
            res += powN[0][i];
            if (res >= MOD) {
                res -= MOD;
            }
        }

        outln(res % MOD);
    }

    long[][] matrixPow(long[][] a, long p) {
        if (p == 0) {
            long[][] res = new long[m][m];
            for (int i = 0; i < m; i++) {
                res[i][i] = 1;
            }
            return res;
        } else if (p % 2 == 0) {
            return matrixPow(matrixMul(a, a), p / 2);
        } else {
            return matrixMul(a, matrixPow(a, p - 1));
        }
    }

    long[][] matrixMul(long[][] a, long[][] b) {
        int n = a.length;
        int m = a[0].length;
        int k = b[0].length;
        long[][] res = new long[n][k];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < k; j++) {
                for (int p = 0; p < m; p++) {
                    long extra = a[i][p] * b[p][j] % MOD;
                    res[i][j] += extra;
                    if (res[i][j] >= MOD) {
                        res[i][j] -= MOD;
                    }
                }
            }
        }
        return res;
    }

    void shuffle(int[] a) {
        int n = a.length;
        for(int i = 0; i < n; i++) {
            int r = i + (int) (Math.random() * (n - i));
            int tmp = a[i];
            a[i] = a[r];
            a[r] = tmp;
        }
    }
    long gcd(long a, long b) {
        while(a != 0 && b != 0) {
            long c = b;
            b = a % b;
            a = c;
        }
        return a + b;
    }
    private void outln(Object o) {
        out.println(o);
    }
    private void out(Object o) {
        out.print(o);
    }
    private void formatPrint(double val) {
        outln(String.format("%.9f%n", val));
    }
    public CFD() throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
        solve();
        out.close();
    }
    public static void main(String[] args) throws IOException {
        new CFD();
    }

    public long[] nextLongArr(int n) throws IOException{
        long[] res = new long[n];
        for(int i = 0; i < n; i++)
            res[i] = nextLong();
        return res;
    }
    public int[] nextIntArr(int n) throws IOException {
        int[] res = new int[n];
        for(int i = 0; i < n; i++)
            res[i] = nextInt();
        return res;
    }
    public String nextToken() {
        while (st == null || !st.hasMoreTokens()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (Exception e) {
                eof = true;
                return null;
            }
        }
        return st.nextToken();
    }
    public String nextString() {
        try {
            return br.readLine();
        } catch (IOException e) {
            eof = true;
            return null;
        }
    }
    public int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }
    public long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }
    public double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
}

import java.io.*;
import java.util.*;

public class D {
    class Writer {
        PrintWriter cout;

        Writer() throws IOException {
            cout = new PrintWriter(System.out);
        }

        Writer(String name) throws IOException {
            cout = new PrintWriter(new FileWriter(name));
        }

        StringBuilder out = new StringBuilder();

        void print(Object a) {
            out.append(a);
        }

        void close() {
            cout.print(out.toString());
            cout.close();
        }
    }

    class Reader {
        BufferedReader in;

        Reader() throws IOException {
            in = new BufferedReader(new InputStreamReader(System.in), 32768);
        }

        Reader(String name) throws IOException {
            in = new BufferedReader(new FileReader(name));
        }

        StringTokenizer tokin = new StringTokenizer("");

        String next() throws IOException {
            if (!tokin.hasMoreTokens()) {
                tokin = new StringTokenizer(in.readLine());
            }
            return tokin.nextToken();
        }

        int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        long nextLong() throws IOException {
            return Long.parseLong(next());
        }
    }

    long mod = (long) (1e9 + 7);
    int m;

    HashMap<Long, Long> h;

    long calck(long n) {
        if (n < 0) {
            return 0;
        } else {
            long ans = 0;
            if (h.containsKey(n)) {
                ans = h.get(n);
            } else {
                long n1 = n / 2;
                long n2 = n - n1;
                ans = (ans + n1 * n2) % mod;
                for (int i = 1; i < m; i++) {
                    ans = (ans + calck(n1 - i) * calck(n2 - (m - i))) % mod;
                    //ans += calck(n1 - i) * calck(n2 - (m - i));
                }
                h.put(n, ans);
            }
            return ans;
        }
    }

    void solve() throws IOException {
        Reader in = new Reader();
        Writer out = new Writer();
        long n = in.nextLong();
        m = in.nextInt();
        h = new HashMap<>();
        for (int i = 0; i < m; i++) {
            h.put((long) i, (long) 1);
        }
        out.print(calck(n));
        out.close();
    }

    public static void main(String[] args) throws IOException {
        new D().solve();
    }
}

import java.io.*;
import java.util.*;

public class Main {
	static long mod=1000000007;
	public static void main(String[] args){
		long n=nl();
		int m=ni();

		long[][] mat=new long[m][m];
		for(int i=0;i<m;i++){
			if(i==0){
				mat[0][0]=1;
				mat[0][m-1]=1;
			}else{
				mat[i][i-1]=i;
			}
		}
		long sisu=n-m+1;
		mat=pow(mat,sisu,mod);
		long res=0;
		for(int i=0;i<m;i++) res+=mat[0][i];

		pl(res);
		flush();
	}
	static long[][] mul(long[][] a,long[][] b,long mod){
		long[][] res=new long[a.length][b[0].length];
		for(int i=0;i<a.length;i++){
			for(int j=0;j<b[0].length;j++){
				for(int k=0;k<a[i].length;k++){
					res[i][j]+=a[i][k]*b[k][j]%mod;
					res[i][j]%=mod;
				}
			}
		}
		return res;
	}
	static long[][] pow(long[][] a,long b,long mod){
		long[][]res=new long[a.length][a.length];
		for(int i=0;i<a.length;i++) res[i][i]=1;
		while(b>0){
			if(b%2==1) res=mul(res,a,mod);
			a=mul(a,a,mod);
			b/=2;
		}
		return res;
	}

	private static final byte[] buffer = new byte[1024];
	private static int ptr = 0;
	private static int buflen = 0;
	private static boolean hasNextByte() {
		if (ptr < buflen)  return true;
		else{
			ptr = 0;
			try {
				buflen = System.in.read(buffer);
			} catch (IOException e) {e.printStackTrace();}
			if (buflen <= 0)  return false;
		}
		return true;
	}
	private static int readByte() { return hasNextByte() ? buffer[ptr++] : -1;}
	private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
	private static void skipUnprintable() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++;}
	public static boolean hasNext() { skipUnprintable(); return hasNextByte();}
	public static String next() {
		if (!hasNext()) throw new NoSuchElementException();
		StringBuilder sb = new StringBuilder();
		for(int b = readByte();isPrintableChar(b);b = readByte()) {
			sb.appendCodePoint(b);
		}
		return sb.toString();
	}
	public static int nextInt() {return (int)nextLong();}
	public static long nextLong() {
		if (!hasNext()) throw new NoSuchElementException();
		long n = 0;
		boolean minus = false;
		int b = readByte();
		if (b == '-') {
			minus = true;
			b = readByte();
		}
		if (b < '0' || '9' < b)  throw new NumberFormatException();
		while(true){
			if ('0' <= b && b <= '9') n = n * 10 + b-'0';
			else if(b == -1 || !isPrintableChar(b)) return minus ? -n : n;
			else throw new NumberFormatException();
			b = readByte();
		}
	}
	public static long[] nextLongArray(int i){
		long[] result=new long[i];
		for(int j=0;j<i;j++)  result[j]=nextLong();
		return result;
	}
	public static void nextLongArray(long[]... arrays){
		for(int j=0;j<arrays[0].length;j++)
			for(long[] array:arrays) array[j]=nextLong();
	}
	public static int[] nextIntArray(int i){
		int[] result=new int[i];
		for(int j=0;j<i;j++)  result[j]=nextInt();
		return result;
	}
	public static void nextIntArray(int[]... arrays){
		for(int j=0;j<arrays[0].length;j++)
			for(int[] array:arrays)  array[j]=nextInt();
	}
	public static int ni(){return nextInt();}
	public static long nl(){return nextLong();}
	public static int[] nia(int n){return nextIntArray(n);}
	public static long[] nla(int n){return nextLongArray(n);}
	public static String ne(){return next();}

	static StringBuilder sb=new StringBuilder();
	public static void flush(){
		System.out.print(sb);
		sb=new StringBuilder();
	}
	public static void pr(Object o){sb.append(o);}
	public static void pl(Object o){sb.append(o).append("\n");}
	public static void pl(){sb.append("\n");}
	public static int lastLowerIndex(long[] array,long lo){return lastLowerOrEqualIndex(array,lo-1);}
	public static int lastLowerOrEqualIndex(long[] array,long lo){
		int res=Arrays.binarySearch(array,lo);
		return res<0?-res-2:res;
	}
	public static long gcd(long a,long b){
		if(a>b)a%=b;
		while(a>0){
			b%=a;
			if(b==0)return a;
			a%=b;
		}
		return b;
	}
	public static long modPow(long a,long b,long mod){
		long c=1;
		while(b>0){
			if(b%2==1)  c=(c*a)%mod;
			a=(a*a)%mod;
			b/=2;
		}
		return c;
	}
	public static long inv(long a,long mod){
		long b=mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d=a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		return p < 0 ? p + mod : p;
	}
	static long time=0;
	public static void time(){
		if(time==0) time=System.nanoTime();
		else{
			long t=System.nanoTime();
			pl((t-time)/1000000000.0+"sec");
			time=t;
		}
	}
	public static Integer[] sortedIndex(long[] a){
            Integer[] res=new Integer[a.length];
            for(int i=0;i<a.length;i++)	res[i]=i;
            mergesortIndex(res,a,0,a.length);
            return res;
        }
        private static Integer[] stem=new Integer[200005];
        private static void mergesortIndex(Integer[] index,long[] a, int s, int e){//uwi's
            if(e - s <= 1)return;
            int h = s+e>>1;
            mergesortIndex(index,a, s, h);
            mergesortIndex(index,a, h, e);
            int p = 0;
            int i= s, j = h;
            for(;i < h && j < e;)stem[p++] = a[(int)index[i]] < a[(int)index[j]] ? index[i++] : index[j++];
            while(i < h)stem[p++] = index[i++];
            while(j < e)stem[p++] = index[j++];
            System.arraycopy(stem, 0, index, s, e-s);
        }
        private static long[] stmp=new long[200005];
        private static void mergesort(long[] a, int s, int e){//uwi's
            if(e - s <= 1)return;
            int h = s+e>>1;
            mergesort(a, s, h);
            mergesort(a, h, e);
            int p = 0;
            int i= s, j = h;
            for(;i < h && j < e;)stmp[p++] = a[i] < a[j] ? a[i++] : a[j++];
            while(i < h)stmp[p++] = a[i++];
            while(j < e)stmp[p++] = a[j++];
            System.arraycopy(stmp, 0, a, s, e-s);
        }
}

import java.io.*;
import java.util.*;

public class Main {
	static long mod=1000000007;
	public static void main(String[] args){
		long n=nl();
		int m=ni();

		if(n<m){
			pl(1);
			flush();
			return;
		}
		long[][] mat=new long[m][m];
		for(int i=0;i<m;i++){
			if(i==0){
				mat[0][0]=1;
				mat[0][m-1]=1;
			}else{
				mat[i][i-1]=i;
			}
		}
		long sisu=n-m+1;
		mat=pow(mat,sisu,mod);
		long res=0;
		for(int i=0;i<m;i++) res=(res+mat[0][i])%mod;

		pl(res);
		flush();
	}
	static long[][] mul(long[][] a,long[][] b,long mod){
		long[][] res=new long[a.length][b[0].length];
		for(int i=0;i<a.length;i++){
			for(int j=0;j<b[0].length;j++){
				for(int k=0;k<a[i].length;k++){
					res[i][j]+=a[i][k]*b[k][j]%mod;
					res[i][j]%=mod;
				}
			}
		}
		return res;
	}
	static long[][] pow(long[][] a,long b,long mod){
		long[][]res=new long[a.length][a.length];
		for(int i=0;i<a.length;i++) res[i][i]=1;
		while(b>0){
			if(b%2==1) res=mul(res,a,mod);
			a=mul(a,a,mod);
			b/=2;
		}
		return res;
	}

	private static final byte[] buffer = new byte[1024];
	private static int ptr = 0;
	private static int buflen = 0;
	private static boolean hasNextByte() {
		if (ptr < buflen)  return true;
		else{
			ptr = 0;
			try {
				buflen = System.in.read(buffer);
			} catch (IOException e) {e.printStackTrace();}
			if (buflen <= 0)  return false;
		}
		return true;
	}
	private static int readByte() { return hasNextByte() ? buffer[ptr++] : -1;}
	private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
	private static void skipUnprintable() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++;}
	public static boolean hasNext() { skipUnprintable(); return hasNextByte();}
	public static String next() {
		if (!hasNext()) throw new NoSuchElementException();
		StringBuilder sb = new StringBuilder();
		for(int b = readByte();isPrintableChar(b);b = readByte()) {
			sb.appendCodePoint(b);
		}
		return sb.toString();
	}
	public static int nextInt() {return (int)nextLong();}
	public static long nextLong() {
		if (!hasNext()) throw new NoSuchElementException();
		long n = 0;
		boolean minus = false;
		int b = readByte();
		if (b == '-') {
			minus = true;
			b = readByte();
		}
		if (b < '0' || '9' < b)  throw new NumberFormatException();
		while(true){
			if ('0' <= b && b <= '9') n = n * 10 + b-'0';
			else if(b == -1 || !isPrintableChar(b)) return minus ? -n : n;
			else throw new NumberFormatException();
			b = readByte();
		}
	}
	public static long[] nextLongArray(int i){
		long[] result=new long[i];
		for(int j=0;j<i;j++)  result[j]=nextLong();
		return result;
	}
	public static void nextLongArray(long[]... arrays){
		for(int j=0;j<arrays[0].length;j++)
			for(long[] array:arrays) array[j]=nextLong();
	}
	public static int[] nextIntArray(int i){
		int[] result=new int[i];
		for(int j=0;j<i;j++)  result[j]=nextInt();
		return result;
	}
	public static void nextIntArray(int[]... arrays){
		for(int j=0;j<arrays[0].length;j++)
			for(int[] array:arrays)  array[j]=nextInt();
	}
	public static int ni(){return nextInt();}
	public static long nl(){return nextLong();}
	public static int[] nia(int n){return nextIntArray(n);}
	public static long[] nla(int n){return nextLongArray(n);}
	public static String ne(){return next();}

	static StringBuilder sb=new StringBuilder();
	public static void flush(){
		System.out.print(sb);
		sb=new StringBuilder();
	}
	public static void pr(Object o){sb.append(o);}
	public static void pl(Object o){sb.append(o).append("\n");}
	public static void pl(){sb.append("\n");}
	public static int lastLowerIndex(long[] array,long lo){return lastLowerOrEqualIndex(array,lo-1);}
	public static int lastLowerOrEqualIndex(long[] array,long lo){
		int res=Arrays.binarySearch(array,lo);
		return res<0?-res-2:res;
	}
	public static long gcd(long a,long b){
		if(a>b)a%=b;
		while(a>0){
			b%=a;
			if(b==0)return a;
			a%=b;
		}
		return b;
	}
	public static long modPow(long a,long b,long mod){
		long c=1;
		while(b>0){
			if(b%2==1)  c=(c*a)%mod;
			a=(a*a)%mod;
			b/=2;
		}
		return c;
	}
	public static long inv(long a,long mod){
		long b=mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d=a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		return p < 0 ? p + mod : p;
	}
	static long time=0;
	public static void time(){
		if(time==0) time=System.nanoTime();
		else{
			long t=System.nanoTime();
			pl((t-time)/1000000000.0+"sec");
			time=t;
		}
	}
	public static Integer[] sortedIndex(long[] a){
            Integer[] res=new Integer[a.length];
            for(int i=0;i<a.length;i++)	res[i]=i;
            mergesortIndex(res,a,0,a.length);
            return res;
        }
        private static Integer[] stem=new Integer[200005];
        private static void mergesortIndex(Integer[] index,long[] a, int s, int e){//uwi's
            if(e - s <= 1)return;
            int h = s+e>>1;
            mergesortIndex(index,a, s, h);
            mergesortIndex(index,a, h, e);
            int p = 0;
            int i= s, j = h;
            for(;i < h && j < e;)stem[p++] = a[(int)index[i]] < a[(int)index[j]] ? index[i++] : index[j++];
            while(i < h)stem[p++] = index[i++];
            while(j < e)stem[p++] = index[j++];
            System.arraycopy(stem, 0, index, s, e-s);
        }
        private static long[] stmp=new long[200005];
        private static void mergesort(long[] a, int s, int e){//uwi's
            if(e - s <= 1)return;
            int h = s+e>>1;
            mergesort(a, s, h);
            mergesort(a, h, e);
            int p = 0;
            int i= s, j = h;
            for(;i < h && j < e;)stmp[p++] = a[i] < a[j] ? a[i++] : a[j++];
            while(i < h)stmp[p++] = a[i++];
            while(j < e)stmp[p++] = a[j++];
            System.arraycopy(stmp, 0, a, s, e-s);
        }
}

import java.io.IOException;
import java.util.HashMap;
import java.util.NoSuchElementException;

public class Main{
	static int mod = 1000000007;
	static HashMap<Long,Long> map=new HashMap<Long,Long>();
	static long M;
	public static void main(String[] args){

		FastScanner sc = new FastScanner();
		long N = sc.nextLong();
		M = sc.nextLong();
		System.out.println(dp(N));
	}
	private static long dp(long n) {
		if(map.containsKey(n)){
			return map.get(n);
		}else{
			if(n<M){
				return 1;
			}
			long l = n/2;
			long r = n%2==0?n/2:n/2+1;
			long ans = dp(l)*dp(r);
			for(int i=1;i<M;i++){
				if(l-i>=0&&r-(M-i)>=0){
					ans += dp(l-i) * dp(r-(M-i));
				}
			}
			ans %= mod;
			map.put(n,ans);
			return ans;
		}
	}

}

class FastScanner {
    private final java.io.InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;
    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        }else{
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }
    private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
    private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
    private void skipUnprintable() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++;}
    public boolean hasNext() { skipUnprintable(); return hasNextByte();}
    public String next() {
        if (!hasNext()) throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while(isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }
    public long nextLong() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return (minus ? -n : n);
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
    public int nextInt() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return (int) (minus ? -n : n);
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
}

import java.util.*;

import java.io.*;
import java.math.BigInteger;

public class D {
	FastScanner in;
	PrintWriter out;
	boolean systemIO = true;

	public class Pair implements Comparable<Pair> {
		long x;
		long y;

		public Pair(long x, long y) {
			this.x = x;
			this.y = y;
		}

		@Override
		public int compareTo(Pair o) {
			if (x > o.x) {
				return 1;
			}
			if (x < o.x) {
				return -1;
			}
			if (y > o.y) {
				return 1;
			}
			if (y < o.y) {
				return -1;
			}
			return 0;
		}

	}

	public class Fenvik {
		int[] sum;

		public Fenvik(int n) {
			sum = new int[n];
		}

		public void add(int x, int d) {
			for (int i = x; i < sum.length; i = (i | (i + 1))) {
				sum[i] += d;
			}
		}

		public int sum(int r) {
			int ans = 0;
			for (int i = r; i >= 0; i = (i & (i + 1)) - 1) {
				ans += sum[i];
			}
			return ans;
		}

		public int sum(int l, int r) {
			if (l > r) {
				return 0;
			}
			return sum(r) - sum(l - 1);
		}
	}

	public long gcd(long x, long y) {
		if (y == 0) {
			return x;
		}
		if (x == 0) {
			return y;
		}
		return gcd(y, x % y);
	}

	public long[][] pow(long[][] x, long p) {
		if (p == 0) {
			long[][] ans = new long[m][m];
			ans[0][0] = 1;
			ans[1][1] = 1;
			return ans;
		}
		long[][] t = pow(x, p / 2);
		t = multiply(t, t);
		if (p % 2 == 1) {
			t = multiply(t, x);
		}
		return t;
	}

	public long[][] multiply(long[][] a, long[][] b) {
		long[][] ans = new long[a.length][b[0].length];
		for (int i = 0; i < ans.length; i++) {
			for (int j = 0; j < ans[0].length; j++) {
				for (int k = 0; k < b.length; k++) {
					ans[i][j] += a[i][k] * b[k][j];
					ans[i][j] %= mod;
				}
			}
		}
		return ans;
	}

	long mod = 1000000007;
	int m;

	public void solve() {
		long n = in.nextLong();
		m = in.nextInt();
		long[][] a = new long[m][m];
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j <= i; j++) {
				a[i][j]++;
			}
			a[i][m - 1]++;
		}
		long[][] th = new long[m][1];
		for (int i = 0; i < th.length; i++) {
			th[i][0] = 1 + (i + 1) / m;
		}
		a = pow(a, (n - 1) / m);
		th = multiply(a, th);
		out.println(th[(int) ((n - 1) % m)][0]);
	}

	public void run() {
		try {
			if (systemIO) {
				in = new FastScanner(System.in);
				out = new PrintWriter(System.out);
			} else {
				in = new FastScanner(new File("input.txt"));
				out = new PrintWriter(new File("output.txt"));
			}
			solve();

			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner(File f) {
			try {
				br = new BufferedReader(new FileReader(f));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}

		FastScanner(InputStream f) {
			br = new BufferedReader(new InputStreamReader(f));
		}

		String nextLine() {
			try {
				return br.readLine();
			} catch (IOException e) {
				return null;
			}
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

		int nextInt() {
			return Integer.parseInt(next());
		}

		long nextLong() {
			return Long.parseLong(next());
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}

	}

	// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	public static void main(String[] arg) {
		new D().run();
	}
}

import java.lang.*;
import java.math.*;
import java.util.*;
import java.io.*;

public class Main {
    void solve() {
       long n=nl(); m=ni();
       long Mat[][]=new long[m+2][m+2];
       Mat[1][1]=1; Mat[m][1]=1;
       long f[]=new long[m+1];
       f[0]=1;
       for(int i=1;i<=m;i++){
           f[i]=f[i-1];
           if(i-m>=0) f[i]=add(f[i],f[i-m]);
       }
       if(n<=m){
           pw.println(f[(int)n]);
           return;
       }
       for(int j=2;j<=m+1;j++){
           Mat[j-1][j]=1;
       }
       Mat=pow(Mat,n-m);
        long ans=add(mul(f[m],Mat[1][1]),mul(f[1],Mat[m][1]));
        pw.println(ans);

    }
    int m;
    long [][] pow(long A[][],long x){
        if(x==0){
            long C[][]=new long[m+2][m+2];
            for(int i=1;i<=m+1;i++) C[i][i]=1;
            return C;
        }else if(x==1){
            return A;
        }
        long C[][]=pow(A,x/2);
        C=mul(C,C);
        if((x&1)>0) return mul(A,C);
        return C;

    }
    long [][] mul(long A[][],long B[][]){
        long C[][]=new long[m+2][m+2];
        for(int i=1;i<=m+1;i++){
            for(int j=1;j<=m+1;j++){
                for(int k=1;k<=m+1;k++){
                    C[i][j]=add(C[i][j],mul(A[i][k],B[k][j]));
                }
            }
        }
        return C;
    }
    long add(long a,long b){
        a+=b;
        if(a>=M) a-=M;
        return a;
    }
    long mul(long a,long b){
        a*=b;
        if(a>=M )a%=M;
        return a;
    }

    long M = (long)1e9+7;
    InputStream is;
    PrintWriter pw;
    String INPUT = "";

    void run() throws Exception {
        is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        pw = new PrintWriter(System.out);
        long s = System.currentTimeMillis();
        solve();
        pw.flush();
        if (!INPUT.isEmpty()) tr(System.currentTimeMillis() - s + "ms");

    }

    public static void main(String[] args) throws Exception {
        new Main().run();
    }

    private byte[] inbuf = new byte[1024];
    public int lenbuf = 0, ptrbuf = 0;

    private int readByte() {
        if (lenbuf == -1) throw new InputMismatchException();
        if (ptrbuf >= lenbuf) {
            ptrbuf = 0;
            try {
                lenbuf = is.read(inbuf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (lenbuf <= 0) return -1;
        }
        return inbuf[ptrbuf++];
    }

    private boolean isSpaceChar(int c) {
        return !(c >= 33 && c <= 126);
    }

    private int skip() {
        int b;
        while ((b = readByte()) != -1 && isSpaceChar(b)) ;
        return b;
    }

    private double nd() {
        return Double.parseDouble(ns());
    }

    private char nc() {
        return (char) skip();
    }

    private String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    private char[] ns(int n) {
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while (p < n && !(isSpaceChar(b))) {
            buf[p++] = (char) b;
            b = readByte();
        }
        return n == p ? buf : Arrays.copyOf(buf, p);
    }

    private char[][] nm(int n, int m) {
        char[][] map = new char[n][];
        for (int i = 0; i < n; i++) map[i] = ns(m);
        return map;
    }

    private int[] na(int n) {
        int[] a = new int[n];
        for (int i = 0; i < n; i++) a[i] = ni();
        return a;
    }

    private int ni() {
        int num = 0, b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
        if (b == '-') {
            minus = true;
            b = readByte();
        }

        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private long nl() {
        long num = 0;
        int b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
        if (b == '-') {
            minus = true;
            b = readByte();
        }

        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private boolean oj = System.getProperty("ONLINE_JUDGE") != null;

    private void tr(Object... o) {
        if (INPUT.length() > 0) System.out.println(Arrays.deepToString(o));
    }

}

import java.lang.*;
import java.math.*;
import java.util.*;
import java.io.*;

public class Main {
    void solve() {
       long n=nl(); m=ni();
       long Mat[][]=new long[m+2][m+2];
       Mat[1][1]=1; Mat[m][1]=1;
       long f[]=new long[m+1];
       f[0]=1;
       for(int i=1;i<=m;i++){
           f[i]=f[i-1];
           if(i-m>=0) f[i]=add(f[i],f[i-m]);
       }
       if(n<=m){
           pw.println(f[(int)n]);
           return;
       }
       for(int j=2;j<=m+1;j++){
           Mat[j-1][j]=1;
       }
       Mat=modpow(Mat,n-m,M);
        long ans=add(mul(f[m],Mat[1][1]),mul(f[1],Mat[m][1]));
        pw.println(ans);

    }
    int m;
    long [][] pow(long A[][],long x){
        if(x==0){
            long C[][]=new long[m+2][m+2];
            for(int i=1;i<=m+1;i++) C[i][i]=1;
            return C;
        }else if(x==1){
            return A;
        }
        long C[][]=pow(A,x/2);
        C=mul(C,C);
        if((x&1)>0) return mul(A,C);
        return C;

    }
    long [][] mul(long A[][],long B[][]){
        long C[][]=new long[m+2][m+2];
        for(int i=1;i<=m+1;i++){
            for(int j=1;j<=m+1;j++){
                for(int k=1;k<=m+1;k++){
                    C[i][j]=add(C[i][j],mul(A[i][k],B[k][j]));
                }
            }
        }
        return C;
    }
    long[][] modpow(long A[][], long b,long M)
    {
        long C[][]=new long[m+2][m+2];
        for(int i=1;i<=m+1;i++) C[i][i]=1;
        while(b>0)
        {
            if((b&1)>0) C=mul(C,A);
            A=mul(A,A);
            b>>=1;
        }
        return C;
    }
    long add(long a,long b){
        a+=b;
        if(a>=M) a-=M;
        return a;
    }
    long mul(long a,long b){
        a*=b;
        if(a>=M )a%=M;
        return a;
    }

    long M = (long)1e9+7;
    InputStream is;
    PrintWriter pw;
    String INPUT = "";

    void run() throws Exception {
        is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        pw = new PrintWriter(System.out);
        long s = System.currentTimeMillis();
        solve();
        pw.flush();
        if (!INPUT.isEmpty()) tr(System.currentTimeMillis() - s + "ms");

    }

    public static void main(String[] args) throws Exception {
        new Main().run();
    }

    private byte[] inbuf = new byte[1024];
    public int lenbuf = 0, ptrbuf = 0;

    private int readByte() {
        if (lenbuf == -1) throw new InputMismatchException();
        if (ptrbuf >= lenbuf) {
            ptrbuf = 0;
            try {
                lenbuf = is.read(inbuf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (lenbuf <= 0) return -1;
        }
        return inbuf[ptrbuf++];
    }

    private boolean isSpaceChar(int c) {
        return !(c >= 33 && c <= 126);
    }

    private int skip() {
        int b;
        while ((b = readByte()) != -1 && isSpaceChar(b)) ;
        return b;
    }

    private double nd() {
        return Double.parseDouble(ns());
    }

    private char nc() {
        return (char) skip();
    }

    private String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    private char[] ns(int n) {
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while (p < n && !(isSpaceChar(b))) {
            buf[p++] = (char) b;
            b = readByte();
        }
        return n == p ? buf : Arrays.copyOf(buf, p);
    }

    private char[][] nm(int n, int m) {
        char[][] map = new char[n][];
        for (int i = 0; i < n; i++) map[i] = ns(m);
        return map;
    }

    private int[] na(int n) {
        int[] a = new int[n];
        for (int i = 0; i < n; i++) a[i] = ni();
        return a;
    }

    private int ni() {
        int num = 0, b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
        if (b == '-') {
            minus = true;
            b = readByte();
        }

        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private long nl() {
        long num = 0;
        int b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
        if (b == '-') {
            minus = true;
            b = readByte();
        }

        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private boolean oj = System.getProperty("ONLINE_JUDGE") != null;

    private void tr(Object... o) {
        if (INPUT.length() > 0) System.out.println(Arrays.deepToString(o));
    }

}

import java.io.*;
import java.util.*;

public class D
{

	static StringBuilder st = new StringBuilder();

	// dp(n ) = dp(n - 1) ->> put normal gem   + dp(n - m ) -->> divide magic gem to m elements

	static final int MOD = (int)1e9 + 7 ;
	static int [][] mat ;

	public static void main(String[] args) throws Exception
	{
		Scanner sc = new Scanner(System.in) ;
		PrintWriter out = new PrintWriter(System.out) ;

		long n = sc.nextLong() ; int m = sc.nextInt() ;

		mat = new int [m][m] ;

		mat[0][0] = 1 ; mat[0][m - 1] = 1 ;
		for(int i = 1 ;i < m ;i++)
			mat[i][i - 1] = 1 ;

		if(n < m)
			out.println(1);
		else
			out.println(pow(mat, n - m - 1, m));
		out.flush();
		out.close();

	}

	static int pow(int [][] mat , long n , int m)
	{
		int [][] res = new int [m][m] ;

		for(int i = 0 ;i < m ; i++) res [i][i] = 1 ;

		while(n > 0)
		{
			if((n & 1) == 1)
				res = mult(mat, res) ;

			mat = mult(mat , mat) ;
			n >>= 1  ;
		}

		int ans = 0 ;
		for(int l = 0 ; l < m ; l++)
		{
			ans += res[0][l] + 1 ;
			ans %= MOD ;
		}

		return ans % MOD;
	}

	static int [][] mult(int [][] a , int [][] b)
	{
		int [][] res = new int [a.length][a.length] ;
		int m = a.length ;
		for(int i = 0 ;i < m ; i++) res [i][i] = 1 ;

		for(int i = 0 ;i < m; i ++)
			for(int j = 0 ; j < m ; j ++ )
				for(int l = 0 ; l < m ; l++)
				{
					res[i][j] += (1l * a[i][l] * b[l][j] % MOD)  ;
					res[i][j] %= MOD ;
				}

		return res ;
	}
	static class Scanner
	{
		BufferedReader br;
		StringTokenizer st;

		Scanner(InputStream in)
		{
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		String next() throws Exception
		{
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		int nextInt() throws Exception { return Integer.parseInt(next()); }

		long nextLong() throws Exception { return Long.parseLong(next()); }

		double nextDouble() throws Exception { return Double.parseDouble(next());}

	}

	static void shuffle(int[] a)
	{
		int n = a.length;
		for (int i = 0; i < n; i++)
		{
			int r = i + (int) (Math.random() * (n - i));
			int tmp = a[i];
			a[i] = a[r];
			a[r] = tmp;
		}
	}

}

import java.io.*;
import java.util.*;

public class D
{

	static StringBuilder st = new StringBuilder();

	// dp(n ) = dp(n - 1) ->> put normal gem   + dp(n - m ) -->> divide magic gem to m elements

	static final int MOD = (int)1e9 + 7 ;
	static int [][] mat ;

	public static void main(String[] args) throws Exception
	{
		Scanner sc = new Scanner(System.in) ;
		PrintWriter out = new PrintWriter(System.out) ;

		long n = sc.nextLong() ; int m = sc.nextInt() ;

		mat = new int [m][m] ;

		mat[0][0] = 1 ; mat[0][m - 1] = 1 ;

		for(int i = 1 ;i < m ;i++) mat[i][i - 1] = 1 ;

		if(n < m)
			out.println(1);
		else
			out.println(pow(mat, n - m ));

		out.flush();
		out.close();

	}

	static int pow(int [][] mat , long n)
	{
		int m = mat.length ;
		int [][] res = new int [m][m] ;

		for(int i = 0 ;i < m ; i++) res [i] = mat[i].clone() ;

		while(n > 0)
		{
			if((n & 1) == 1)
				res = mult(mat, res) ;

			mat = mult(mat , mat) ;
			n >>= 1  ;
		}

		return (int)((1l * res[0][0] + res[0][m - 1]) % MOD);
	}

	static int [][] mult(int [][] a , int [][] b)
	{
		int [][] res = new int [a.length][a.length] ;
		int m = a.length ;

		for(int i = 0 ;i < m; i ++)
			for(int j = 0 ; j < m ; j ++ )
				for(int l = 0 ; l < m ; l++)
				{
					res[i][j] += (int)((1l * a[i][l] * b[l][j] % MOD)) ;
					res[i][j] %= MOD ;
				}

		return res ;
	}
	static class Scanner
	{
		BufferedReader br;
		StringTokenizer st;

		Scanner(InputStream in)
		{
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		String next() throws Exception
		{
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		int nextInt() throws Exception { return Integer.parseInt(next()); }

		long nextLong() throws Exception { return Long.parseLong(next()); }

		double nextDouble() throws Exception { return Double.parseDouble(next());}

	}

	static void shuffle(int[] a)
	{
		int n = a.length;
		for (int i = 0; i < n; i++)
		{
			int r = i + (int) (Math.random() * (n - i));
			int tmp = a[i];
			a[i] = a[r];
			a[r] = tmp;
		}
	}

}

import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Template {
    static int n;
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);

        long n = sc.nextLong();
        int m = sc.nextInt();

        int[][] init = new int[m][1];
        for (int i = 0; i < init.length; i++)
            init[i][0] = 1;
        int[][] mat = new int[m][m];
        mat[0][0] = mat[0][m-1] = 1;
        for (int i = 1; i < m; i++)
            mat[i][i-1] = 1;

        if(n < m)
            System.out.println(1);
        else
        {
            System.out.println(matMul(matPow(mat, n-m+1), init, m, m, 1)[0][0]);
        }
        pw.flush();
        pw.close();
    }

    static int mod = 1000000007;

    static int[][] matMul(int[][] A, int[][] B, int p, int q, int r)	//C(p x r) = A(p x q) x (q x r) -- O(p x q x r)
    {
        int[][] C = new int[p][r];
        for(int i = 0; i < p; ++i)
            for(int j = 0; j < r; ++j)
                for(int k = 0; k < q; ++k)
                    C[i][j] += (int)((1l* A[i][k] * B[k][j])%mod);
        return C;
    }

    /*
     * 4. Square Matrix Exponentiation
     */
    static int[][] matPow(int[][] base, long p)
    {
        int n = base.length;
        int[][] ans = new int[n][n];
        for(int i = 0; i < n; i++)
            ans[i][i] = 1;
        while(p != 0)
        {
            if((p & 1) == 1)
                ans = matMul(ans, base, n, n, n);
            base = matMul(base, base, n, n, n);
            p >>= 1;
        }

        return ans;
    }

    static class Scanner
    {
        StringTokenizer st; BufferedReader br;
        public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}
        public Scanner(String s) throws FileNotFoundException {	br = new BufferedReader(new FileReader(new File(s)));}
        public String next() throws IOException {while (st == null || !st.hasMoreTokens()) st = new StringTokenizer(br.readLine());return st.nextToken();}
        public int nextInt() throws IOException {return Integer.parseInt(next());}
        public long nextLong() throws IOException {return Long.parseLong(next());}
        public String nextLine() throws IOException {return br.readLine();}
        public boolean ready() throws IOException {return br.ready();}
    }
}

import java.util.*;
import java.io.*;

public class MagicGems {
    public static final long MOD = 1000000007L;
    public static final long MODS = MOD*MOD;
    public static void main(String[] args) {
        FastScanner scanner = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);
        long N = scanner.nextLong();
        int M = scanner.nextInt();
        long[][] matrix = new long[M][M];
        for(int i= 0; i  < M-1; i++) {
            matrix[i+1][i] = 1;
        }
        //base cases
        matrix[0][0] = 1;
        matrix[0][M-1] = 1;
        long[] ans = new long[M];
        ans[0] = 1;
        out.println(mPow(matrix, ans, N)[0]);
        out.flush();
    }

    public static long[] mPow (long[][] M,  long[] v, long pow) {
        for(int i= 0; i < v.length; i++) if(v[i] >= MOD) v[i]%=MOD;
        long[][] ret = M;
        //>>>= is an unsigned right shift by 1
        for(;pow> 0; pow >>>=1) {
            if ((pow&1)==1) v = mMul(ret, v);
            ret = mSquare(ret);
        }
        return v;
    }

    public static long[] mMul(long[][] M, long[] v) {
        int m = M.length;
        int n= v.length;
        long[] ret = new long[m];
        for(int i= 0; i < m; i++) {
            long sum = 0;
            for(int k = 0; k < n; k++) {
                sum += M[i][k] * v[k];
                if (sum >= MODS) sum-= MODS;
            }
            ret[i] = sum;
        }
        return ret;
    }

    //need to be a square matrix
    //should have efficiency based on lacking mod ops.
    public static long[][] mSquare(long[][] M) {
        int N = M.length;
        long[][] ret = new long[N][N];
        for(int i = 0; i < N; i++) {
            long[] temp = new long[N];
            for(int k = 0; k < N; k++) {
                for(int j = 0; j < N; j++) {
                    temp[j] += M[i][k] * M[k][j];
                    if (temp[j] >= MODS) temp[j]-=MODS;
                }
            }
            for(int k = 0; k < N; k++) {
                ret[i][k] = (temp[k] %MOD);
            }
        }
        return ret;
    }

    public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(Reader in) {
            br = new BufferedReader(in);
        }

        public FastScanner() {
            this(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String readNextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        int[] readIntArray(int n) {
            int[] a = new int[n];
            for (int idx = 0; idx < n; idx++) {
                a[idx] = nextInt();
            }
            return a;
        }
    }
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class Solution {

	public static void main(String[] args) {
		InputReader in = new InputReader();
		PrintWriter out = new PrintWriter(System.out);
		Thread th = new Thread(null, new Runnable(){public void run(){new Task1().solve(in, out);}},"Task1",1<<24);
		try{
			th.start();
			th.join();
		} catch(InterruptedException e){}
		out.close();
	}

	static class Task1 {
		static final int MOD = 1000000007;
		static final int MAX = 1000002;
		static final boolean DEBUG = false;

		public void solve(InputReader in, PrintWriter out){
			long n = in.nextLong();
			int m = in.nextInt();
			long[][] T = new long[m][m];
			for(int i=0; i<m-1; i++){
				T[i][i+1] = 1;
			}
			T[m-1][0] = T[m-1][m-1] = 1;

			if(DEBUG){
				for(long[] x:T){
					for(long y:x){
						out.print(y+" ");
					}
					out.println();
				}
			}

			// Recurrence for this problem : dp[n] = dp[n-1] + 0 + 0 +.. + dp[n-m]
			// Fn = matrixExponentiation(T, n-1) * F1
			long[][] f1 = new long[m][1];
			for(int i=0; i<m; i++){
				f1[i][0] = 1;
			}
			f1[m-1][0] = 2;

			long[][] ans = multiplyMatrix(matrixExponent(T, n-1), f1);
			if(DEBUG){
				for(long[] x:ans){
					for(long y:x){
						out.print(y+" ");
					}
					out.println();
				}
			}
			out.println(ans[0][0]%MOD);
		}

		private static long[][] matrixExponent(long[][] T, long n) {
			if (n == 1) return T;
			if (n%2 != 0) return multiplyMatrix(T, matrixExponent(T, n-1));
			long X[][] = matrixExponent(T, n/2);
			return multiplyMatrix(X, X);
		}

		private static long[][] multiplyMatrix(long[][] T, long[][] f1) {
			long ans[][] = new long[T.length][f1[0].length];
			for (int i = 0; i < T.length; i++) {
				for (int j = 0; j < f1[0].length; j++) {
					ans[i][j] = 0;
					for (int k = 0; k < f1.length; k++) {
					    ans[i][j] = ans[i][j] + (T[i][k] * f1[k][j]) % MOD;
					}
				}
			}
			return ans;
		}

	}

	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;
		public InputReader() {
			reader = new BufferedReader(new InputStreamReader(System.in));
			tokenizer = null;
		}
		public String next() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
			return tokenizer.nextToken();
		}
		public int nextInt() {
			return Integer.parseInt(next());
		}
		public long nextLong() {
			return Long.parseLong(next());
		}
		public double nextDouble() {
			return Double.parseDouble(next());
		}
		public String nextLine() {
			String s=null;
			try{
				s = reader.readLine();
			} catch(IOException e){
				throw new RuntimeException(e);
			}
			return s;
		}
		public String nextParagraph() {
			String line=null;
			String ans = "";
			try{
				while ((line = reader.readLine()) != null) {
				ans += line+"\n";
				}
			} catch(IOException e){
				throw new RuntimeException(e);
			}
			return ans;
		}
	}
}

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        long MOD = (long) (1e9 + 7);

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long N = in.nextLong();
            int M = in.nextInt();
            int[][] m = new int[M][M];
            int[][] res = new int[M][1];
            m[0][0] = 1;
            m[0][M - 1] = 1;
            res[0][0] = 1;
            for (int i = 1; i < M; i++) {
                m[i][i - 1] = 1;
            }
            MathUtils.Matrix transition = new MathUtils.Matrix(m);
            MathUtils.Matrix end = new MathUtils.Matrix(res);
            end.multiply(transition.pow(N, MOD), MOD);
            out.println(end.m[0][0]);
        }

    }

    static class MathUtils {
        public static class Matrix {
            public int[][] m;
            int rows;
            int cols;

            public Matrix(int[][] m) {
                rows = m.length;
                cols = m[0].length;
                this.m = m;
            }

            public Matrix(int r, int c) {
                m = new int[r][c];
                rows = r;
                cols = c;
            }

            public MathUtils.Matrix getIdentity() {
                assert rows == cols : "Matrix is not square, no identity possible";
                int[][] identity = new int[rows][cols];
                for (int i = 0; i < rows; i++) {
                    identity[i][i] = 1;
                }
                return new MathUtils.Matrix(identity);
            }

            public static MathUtils.Matrix multiply(MathUtils.Matrix a, MathUtils.Matrix b) {
                //does not change in place
                assert a.cols == b.rows : "Input mismatch, rows do not match columns";
                int[][] newMatrix = new int[a.rows][b.cols];
                for (int i = 0; i < a.rows; i++) {
                    for (int k = 0; k < a.cols; k++) {
                        for (int j = 0; j < b.cols; j++) {
                            newMatrix[i][j] += a.m[i][k] * b.m[k][j];
                        }
                    }
                }
                return new MathUtils.Matrix(newMatrix);
            }

            public void multiply(MathUtils.Matrix b, long mod) {
                //changes in place
                assert cols == b.rows : "Input mismatch, rows do not match columns";
                int[][] newMatrix = new int[rows][b.cols];
                for (int i = 0; i < rows; i++) {
                    for (int k = 0; k < cols; k++) {
                        for (int j = 0; j < b.cols; j++) {
                            newMatrix[i][j] += (this.m[i][k] * b.m[k][j]) % mod;
                        }
                    }
                }
                m = newMatrix;
            }

            public MathUtils.Matrix pow(long n, long mod) {
                //does not change in place
                assert rows == cols : "Matrix is not square";
                MathUtils.Matrix res = this.getIdentity();
                MathUtils.Matrix base = new MathUtils.Matrix(this.m);
                while (n > 0) {
                    if ((n & 1) == 1) {
                        res.multiply(base, mod);
                    }
                    base = MathUtils.Matrix.multiply(base, base);
                    n = n >> 1;
                }
                return res;
            }

        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }
}

import java.util.*;

public class Dcode {

    static  int m;
    static  int mod = 1000000007;

    static  long[][] mul(long a[][],long n){
        if(n<=1){
            return a;
        }

        long matrix[][] = new long[m][m];
        for(int i=0;i<m;i++){
            matrix[i][i] = 1;

        }

        while(n>0){
                if((n&1) == 1){
                        matrix = mm(matrix,a);

                }

                    a = mm(a,a);

                        n = n>>1;
        }

         return matrix;

    }

    static long[][] mm(long a[][],long b[][]){
        long c[][] = new long[m][m];

        for(int i=0;i<m;i++){
            for(int j=0;j<m;j++){
                long sum = 0;
                for(int k=0;k<m;k++){
                    sum = (sum + a[i][k]*b[k][j])%mod;
                }

                c[i][j] = sum;
            }
        }

        return c;
    }

    public static  void main(String args[]){

        Scanner s = new Scanner(System.in);
        long n = s.nextLong();
        m = s.nextInt();
        if(n<m){
            System.out.println(1);
            return;
        }
        long a[][] = new long[m][m];

        a[0][0] = 1;
        a[0][m-1] = 1;
        for(int i=1;i<m;i++){
            a[i][i-1] = 1;
        }

        long ans  = 0;

        long h[][] = mul(a,n-m);

        ans = 2*h[0][0];

        for(int i=1;i<m;i++){
            ans = (ans + h[0][i])%mod;
        }

        System.out.println(ans);

    }
}

import java.util.*;

public class Dcode {

    static  int m;
    static  int mod = 1000000007;

    static  long[][] mul(long a[][],long n){
        if(n<=1){
            return a;
        }

        long matrix[][] = new long[m][m];
        for(int i=0;i<m;i++){
            matrix[i][i] = 1;

        }

        while(n>0){
                if((n&1) == 1){
                        matrix = mm(matrix,a);

                }

                    a = mm(a,a);

                        n = n>>1;
        }

         return matrix;

    }

    static long[][] mm(long a[][],long b[][]){
        long c[][] = new long[m][m];

        for(int i=0;i<m;i++){
            for(int j=0;j<m;j++){
                long sum = 0;
                for(int k=0;k<m;k++){
                    sum = (sum + a[i][k]*b[k][j])%mod;
                }

                c[i][j] = sum;
            }
        }

        return c;
    }

    public static  void main(String args[]){

        Scanner s = new Scanner(System.in);
        long n = s.nextLong();
        m = s.nextInt();
        if(n<m){
            System.out.println(1);
            return;
        }
        if(n==m){
            System.out.println(n);
            return;
        }
        long a[][] = new long[m][m];

        a[0][0] = 1;
        a[0][m-1] = 1;
        for(int i=1;i<m;i++){
            a[i][i-1] = 1;
        }

        long ans  = 0;

        long h[][] = mul(a,n-m);

        ans = 2*h[0][0];

        for(int i=1;i<m;i++){
            ans = (ans + h[0][i])%mod;
        }

        System.out.println(ans);

    }
}

import java.util.*;

public class Dcode {

    static  int m;
    static  int mod = 1000000007;

    static  long[][] mul(long a[][],long n){
        if(n<=1){
            return a;
        }

        long matrix[][] = new long[m][m];
        for(int i=0;i<m;i++){
            matrix[i][i] = 1;

        }

        while(n>0){
                if((n&1) == 1){
                        matrix = mm(matrix,a);

                }

                    a = mm(a,a);

                        n = n>>1;
        }

         return matrix;

    }

    static long[][] mm(long a[][],long b[][]){
        long c[][] = new long[m][m];

        for(int i=0;i<m;i++){
            for(int j=0;j<m;j++){
                long sum = 0;
                for(int k=0;k<m;k++){
                    sum = (sum + a[i][k]*b[k][j])%mod;
                }

                c[i][j] = sum;
            }
        }

        return c;
    }

    public static  void main(String args[]){

        Scanner s = new Scanner(System.in);
        long n = s.nextLong();
        m = s.nextInt();
        long a[][] = new long[m][m];

        a[0][0] = 1;
        a[0][m-1] = 1;
        for(int i=1;i<m;i++){
            a[i][i-1] = 1;
        }

        long ans  = 0;

        long h[][] = mul(a,n-m);

        ans = 2*h[0][0];

        for(int i=1;i<m;i++){
            ans = (ans + h[0][i])%mod;
        }

        System.out.println(ans);

    }
}

import java.util.*;

public class Dcode {

    static  int m;
    static  int mod = 1000000007;

    static  long[][] mul(long a[][],long n){
        if(n<=1){
            return a;
        }

        long matrix[][] = new long[m][m];
        for(int i=0;i<m;i++){
            matrix[i][i] = 1;

        }

        while(n>0){
                if((n&1) == 1){
                        matrix = mm(matrix,a);

                }

                    a = mm(a,a);

                        n = n>>1;
        }

         return matrix;

    }

    static long[][] mm(long a[][],long b[][]){
        long c[][] = new long[m][m];

        for(int i=0;i<m;i++){
            for(int j=0;j<m;j++){
                long sum = 0;
                for(int k=0;k<m;k++){
                    sum = (sum + a[i][k]*b[k][j])%mod;
                }

                c[i][j] = sum;
            }
        }

        return c;
    }

    public static  void main(String args[]){

        Scanner s = new Scanner(System.in);
        long n = s.nextLong();
        m = s.nextInt();
        if(n<m){
            System.out.println(1);
            return;
        }
        if(n==m){
            System.out.println(n);
        }
        long a[][] = new long[m][m];

        a[0][0] = 1;
        a[0][m-1] = 1;
        for(int i=1;i<m;i++){
            a[i][i-1] = 1;
        }

        long ans  = 0;

        long h[][] = mul(a,n-m);

        ans = 2*h[0][0];

        for(int i=1;i<m;i++){
            ans = (ans + h[0][i])%mod;
        }

        System.out.println(ans);

    }
}

import java.util.*;
import java.io.*;
public class HelloWorld{

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;
        public Scanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

        public Scanner(FileReader fileReader) {
            br = new BufferedReader(fileReader);
        }

        public String next() throws IOException {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public String nextLine() throws IOException {
            return br.readLine();
        }

        public boolean ready() throws IOException {
            return br.ready();
        }
    }

    static long mod=(long)1e9+7;
    static long[][] I;

     public static void main (String []args) throws IOException {
         Scanner sc = new Scanner(System.in);
         long n = sc.nextLong();int m = sc.nextInt();
         I=new long[m][m];
         long[][] M = new long[m][m];
         for(int i=1;i<m;i++){
             I[i][i] = M[i-1][i] = 1L;

         }
         I[0][0] = M[0][0]=M[m-1][0]=1L;

         M=exp(M,n);
         System.out.print(M[0][0]);
    }
    public static long[][] exp(long[][] M,long n){
        long[][] res = I;
        if(n==0) return I;
        if(n==1) return M;
        while(n>0){
        if(n%2!=0)res=mult(res,M);
        n/=2;
        M=mult(M,M);
        }
        return res;
    }
    public static long[][] mult(long[][]p ,long[][] q){
        long[][] r = new long[p.length][q[0].length];
        for(int i=0;i<p.length;i++){
            for(int j=0;j<q[0].length;j++){
                for(int k=0;k<q.length;k++){
                    r[i][j]+=p[i][k]*q[k][j];
                }
            }
        }
        return r;
    }
}

// package Practice.CF1117;

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class CF1117D {
    static FastReader s;
    static PrintWriter out;
    static String INPUT = "4 2\n";

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
        out = new PrintWriter(System.out);
        s = new FastReader(oj);
        long n = s.nextLong();
        long m = s.nextLong();
        long k = n/m;
        long firstTerm = n - m + 1;
        BigInteger ans;
        if(k != 1) {
            BigInteger k2 = BigInteger.valueOf(k/2);
            BigInteger fi2 = BigInteger.valueOf(2).multiply(BigInteger.valueOf(firstTerm));
            BigInteger km = BigInteger.valueOf(k).multiply(BigInteger.valueOf(m));
            BigInteger mB = BigInteger.valueOf(m);
            ans = k2.multiply(fi2.subtract(km).add(mB));
        } else {
            ans = BigInteger.valueOf(firstTerm);
        }
        out.println(ans.add(BigInteger.ONE).mod(BigInteger.valueOf(1000000007)));
        if (!oj) {
            System.out.println(Arrays.deepToString(new Object[]{System.currentTimeMillis() - time + " ms"}));
        }
        out.flush();
    }

    private static class Maths {
        static ArrayList<Long> printDivisors(long n) {
            // Note that this loop runs till square root
            ArrayList<Long> list = new ArrayList<>();
            for (long i = 1; i <= Math.sqrt(n); i++) {
                if (n % i == 0) {
                    if (n / i == i) {
                        list.add(i);
                    } else {
                        list.add(i);
                        list.add(n / i);
                    }
                }
            }
            return list;
        }

        //    GCD - Using Euclid theorem.
        private static long gcd(long a, long b) {
            if (b == 0) {
                return a;
            }

            return gcd(b, a % b);
        }

        //    Extended euclidean algorithm
//    Used to solve equations of the form ax + by = gcd(a,b)
//    return array [d, a, b] such that d = gcd(p, q), ap + bq = d
        static long[] extendedEuclidean(long p, long q) {
            if (q == 0)
                return new long[]{p, 1, 0};

            long[] vals = extendedEuclidean(q, p % q);
            long d = vals[0];
            long a = vals[2];
            long b = vals[1] - (p / q) * vals[2];
            return new long[]{d, a, b};
        }

        // X ^ y mod p
        static long power(long x, long y, long p) {
            long res = 1;
            x = x % p;

            while (y > 0) {
                if ((y & 1) == 1)
                    res = (res * x) % p;
                y = y >> 1;
                x = (x * x) % p;
            }
            return res;
        }

        // Returns modulo inverse of a
        // with respect to m using extended
        // Euclid Algorithm. Refer below post for details:
        // https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/
        static long inv(long a, long m) {
            long m0 = m, t, q;
            long x0 = 0, x1 = 1;

            if (m == 1)
                return 0;

            // Apply extended Euclid Algorithm
            while (a > 1) {
                q = a / m;
                t = m;
                m = a % m;
                a = t;
                t = x0;
                x0 = x1 - q * x0;
                x1 = t;
            }

            // Make x1 positive
            if (x1 < 0)
                x1 += m0;

            return x1;
        }

        // k is size of num[] and rem[].
        // Returns the smallest number
        // x such that:
        // x % num[0] = rem[0],
        // x % num[1] = rem[1],
        // ..................
        // x % num[k-2] = rem[k-1]
        // Assumption: Numbers in num[] are pairwise
        // coprime (gcd for every pair is 1)
        static long findMinX(long num[], long rem[], long k) {
            int prod = 1;
            for (int i = 0; i < k; i++)
                prod *= num[i];

            int result = 0;
            for (int i = 0; i < k; i++) {
                long pp = prod / num[i];
                result += rem[i] * inv(pp, num[i]) * pp;
            }

            return result % prod;
        }
    }

    private static class BS {
        //  Binary search
        private static int binarySearch(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    return mid;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return -1;
        }

        //    First occurence using binary search
        private static int binarySearchFirstOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    high = mid - 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }

        //    Last occurenece using binary search
        private static int binarySearchLastOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    low = mid + 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }
    }

    private static class arrays {
        // Merge sort
        static void merge(int arr[], int l, int m, int r) {
            int n1 = m - l + 1;
            int n2 = r - m;
            int L[] = new int[n1];
            int R[] = new int[n2];
            for (int i = 0; i < n1; ++i)
                L[i] = arr[l + i];
            for (int j = 0; j < n2; ++j)
                R[j] = arr[m + 1 + j];
            int i = 0, j = 0;
            int k = l;
            while (i < n1 && j < n2) {
                if (L[i] <= R[j]) {
                    arr[k] = L[i];
                    i++;
                } else {
                    arr[k] = R[j];
                    j++;
                }
                k++;
            }

            while (i < n1) {
                arr[k] = L[i];
                i++;
                k++;
            }

            while (j < n2) {
                arr[k] = R[j];
                j++;
                k++;
            }
        }

        static void sort(int arr[], int l, int r) {
            if (l < r) {
                int m = (l + r) / 2;
                sort(arr, l, m);
                sort(arr, m + 1, r);
                merge(arr, l, m, r);
            }
        }

        static void sort(int[] arr) {
            sort(arr, 0, arr.length - 1);
        }
    }

    private static class UnionFindDisjointSet {
        int[] parent;
        int[] size;
        int n;
        int size1;

        public UnionFindDisjointSet(int n) {
            this.n = n;
            this.parent = new int[n];
            this.size = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }

            for (int i = 0; i < n; i++) {
                size[i] = 1;
            }

            this.size1 = n;
        }

        private int numDisjointSets() {
            System.out.println(size1);
            return size1;
        }

        private boolean find(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return true;
            }
            return false;
        }

        private int root(int b) {
            while (parent[b] != b) {
                parent[b] = parent[parent[b]];
                b = parent[b];
            }
            return b;
        }

        private void union(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return;
            }

            if (size[rootA] < size[rootB]) {
                parent[rootA] = parent[rootB];
                size[rootB] += size[rootA];
            } else {
                parent[rootB] = parent[rootA];
                size[rootA] += size[rootB];
            }
            size1--;
            System.out.println(Arrays.toString(parent));
        }
    }

    private static class SegTree {
        int[] st;
        int[] arr;

        public SegTree(int[] arr) {
            this.arr = arr;
            int size = (int) Math.ceil(Math.log(arr.length) / Math.log(2));
            st = new int[(int) ((2 * Math.pow(2, size)) - 1)];
            buildSegmentTree(1, 0, arr.length - 1);
        }

        //**********JUST CALL THE CONSTRUCTOR, THIS FUNCTION WILL BE CALLED AUTOMATICALLY******
        private void buildSegmentTree(int index, int L, int R) {
            if (L == R) {
                st[index] = arr[L];
                return;
            }

            buildSegmentTree(index * 2, L, (L + R) / 2);
            buildSegmentTree(index * 2 + 1, (L + R) / 2 + 1, R);
//          Replace this line if you want to change the function of the Segment tree.
            st[index] = Math.min(st[index * 2], st[index * 2 + 1]);
        }

        //***********We have to use this function **************
        private int Query(int queL, int queR) {
            return Query1(1, 0, arr.length - 1, queL, queR);
        }

        //This is a helper function.
        //************* DO NOT USE THIS ****************
        private int Query1(int index, int segL, int segR, int queL, int queR) {
            if (queL > segR || queR < segL) {
                return -1;
            }

            if (queL <= segL && queR >= segR) {
                return st[index];
            }

            int ans1 = Query1(index * 2, segL, (segL + segR) / 2, queL, queR);
            int ans2 = Query1(index * 2 + 1, (segL + segR) / 2 + 1, segR, queL, queR);
            if (ans1 == -1) {
                return ans2;
            }

            if (ans2 == -1) {
                return ans1;
            }
//             Segment tree implemented for range minimum query. Change the below line to change the function.
            return Math.min(ans1, ans2);
        }

        private void update(int idx, int val) {
            update1(1, 0, arr.length - 1, idx, val);
        }

        private void update1(int node, int queL, int queR, int idx, int val) {
            // idx - index to be updated in the array
            // node - index to be updated in the seg tree
            if (queL == queR) {
                // Leaf node
                arr[idx] += val;
                st[node] += val;
            } else {
                int mid = (queL + queR) / 2;
                if (queL <= idx && idx <= mid) {
                    // If idx is in the left child, recurse on the left child
                    update1(2 * node, queL, mid, idx, val);
                } else {
                    // if idx is in the right child, recurse on the right child
                    update1(2 * node + 1, mid + 1, queR, idx, val);
                }
                // Internal node will have the min of both of its children
                st[node] = Math.min(st[2 * node], st[2 * node + 1]);
            }
        }

    }

    private static class FastReader {
        InputStream is;

        public FastReader(boolean onlineJudge) {
            is = onlineJudge ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        }

        byte[] inbuf = new byte[1024];
        public int lenbuf = 0, ptrbuf = 0;

        int readByte() {
            if (lenbuf == -1)
                throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0)
                    return -1;
            }
            return inbuf[ptrbuf++];
        }

        boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b))
                ;
            return b;
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        char nextChar() {
            return (char) skip();
        }

        String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        String nextLine() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while ((!isSpaceChar(b) || b == ' ')) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        char[][] nextMatrix(int n, int m) {
            char[][] map = new char[n][];
            for (int i = 0; i < n; i++)
                map[i] = next(m);
            return map;
        }

        int[] nextIntArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        long[] nextLongArray(int n) {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
                a[i] = nextLong();
            return a;
        }

        int[][] next2DInt(int n, int m) {
            int[][] arr = new int[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextIntArray(m);
            }
            return arr;
        }

        long[][] next2DLong(int n, int m) {
            long[][] arr = new long[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLongArray(m);
            }
            return arr;
        }

        int[] shuffle(int[] arr) {
            Random r = new Random();
            for (int i = 1, j; i < arr.length; i++) {
                j = r.nextInt(i);
                arr[i] = arr[i] ^ arr[j];
                arr[j] = arr[i] ^ arr[j];
                arr[i] = arr[i] ^ arr[j];
            }
            return arr;
        }

        int[] uniq(int[] arr) {
            Arrays.sort(arr);
            int[] rv = new int[arr.length];
            int pos = 0;
            rv[pos++] = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if (arr[i] != arr[i - 1]) {
                    rv[pos++] = arr[i];
                }
            }
            return Arrays.copyOf(rv, pos);
        }
    }

}

// package Practice.CF1117;

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class CF1117D {
    static FastReader s;
    static PrintWriter out;
    static String INPUT = "1000000000000000000 2\n";
    static int mod = 1000_000_007;

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
        out = new PrintWriter(System.out);
        s = new FastReader(oj);
        long n = s.nextLong() ;
        long m = s.nextLong() ;
        long k = n/m ;
        long firstTerm = n - m + 1;
        long ans;
        if(k != 1) {
            long a = (k/2) % mod;
            long b = (2% mod * firstTerm% mod) % mod;
            long km = (k % mod) * (m % mod) % mod;
            ans = ((a % mod) * ((b - km + m) % mod) % mod);
        } else {
            ans = firstTerm;
        }
        out.println((ans+1)% mod);
        if (!oj) {
            System.out.println(Arrays.deepToString(new Object[]{System.currentTimeMillis() - time + " ms"}));
        }
        out.flush();
    }

    private static class Maths {
        static ArrayList<Long> printDivisors(long n) {
            // Note that this loop runs till square root
            ArrayList<Long> list = new ArrayList<>();
            for (long i = 1; i <= Math.sqrt(n); i++) {
                if (n % i == 0) {
                    if (n / i == i) {
                        list.add(i);
                    } else {
                        list.add(i);
                        list.add(n / i);
                    }
                }
            }
            return list;
        }

        //    GCD - Using Euclid theorem.
        private static long gcd(long a, long b) {
            if (b == 0) {
                return a;
            }

            return gcd(b, a % b);
        }

        //    Extended euclidean algorithm
//    Used to solve equations of the form ax + by = gcd(a,b)
//    return array [d, a, b] such that d = gcd(p, q), ap + bq = d
        static long[] extendedEuclidean(long p, long q) {
            if (q == 0)
                return new long[]{p, 1, 0};

            long[] vals = extendedEuclidean(q, p % q);
            long d = vals[0];
            long a = vals[2];
            long b = vals[1] - (p / q) * vals[2];
            return new long[]{d, a, b};
        }

        // X ^ y mod p
        static long power(long x, long y, long p) {
            long res = 1;
            x = x % p;

            while (y > 0) {
                if ((y & 1) == 1)
                    res = (res * x) % p;
                y = y >> 1;
                x = (x * x) % p;
            }
            return res;
        }

        // Returns modulo inverse of a
        // with respect to m using extended
        // Euclid Algorithm. Refer below post for details:
        // https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/
        static long inv(long a, long m) {
            long m0 = m, t, q;
            long x0 = 0, x1 = 1;

            if (m == 1)
                return 0;

            // Apply extended Euclid Algorithm
            while (a > 1) {
                q = a / m;
                t = m;
                m = a % m;
                a = t;
                t = x0;
                x0 = x1 - q * x0;
                x1 = t;
            }

            // Make x1 positive
            if (x1 < 0)
                x1 += m0;

            return x1;
        }

        // k is size of num[] and rem[].
        // Returns the smallest number
        // x such that:
        // x % num[0] = rem[0],
        // x % num[1] = rem[1],
        // ..................
        // x % num[k-2] = rem[k-1]
        // Assumption: Numbers in num[] are pairwise
        // coprime (gcd for every pair is 1)
        static long findMinX(long num[], long rem[], long k) {
            int prod = 1;
            for (int i = 0; i < k; i++)
                prod *= num[i];

            int result = 0;
            for (int i = 0; i < k; i++) {
                long pp = prod / num[i];
                result += rem[i] * inv(pp, num[i]) * pp;
            }

            return result % prod;
        }
    }

    private static class BS {
        //  Binary search
        private static int binarySearch(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    return mid;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return -1;
        }

        //    First occurence using binary search
        private static int binarySearchFirstOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    high = mid - 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }

        //    Last occurenece using binary search
        private static int binarySearchLastOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    low = mid + 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }
    }

    private static class arrays {
        // Merge sort
        static void merge(int arr[], int l, int m, int r) {
            int n1 = m - l + 1;
            int n2 = r - m;
            int L[] = new int[n1];
            int R[] = new int[n2];
            for (int i = 0; i < n1; ++i)
                L[i] = arr[l + i];
            for (int j = 0; j < n2; ++j)
                R[j] = arr[m + 1 + j];
            int i = 0, j = 0;
            int k = l;
            while (i < n1 && j < n2) {
                if (L[i] <= R[j]) {
                    arr[k] = L[i];
                    i++;
                } else {
                    arr[k] = R[j];
                    j++;
                }
                k++;
            }

            while (i < n1) {
                arr[k] = L[i];
                i++;
                k++;
            }

            while (j < n2) {
                arr[k] = R[j];
                j++;
                k++;
            }
        }

        static void sort(int arr[], int l, int r) {
            if (l < r) {
                int m = (l + r) / 2;
                sort(arr, l, m);
                sort(arr, m + 1, r);
                merge(arr, l, m, r);
            }
        }

        static void sort(int[] arr) {
            sort(arr, 0, arr.length - 1);
        }
    }

    private static class UnionFindDisjointSet {
        int[] parent;
        int[] size;
        int n;
        int size1;

        public UnionFindDisjointSet(int n) {
            this.n = n;
            this.parent = new int[n];
            this.size = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }

            for (int i = 0; i < n; i++) {
                size[i] = 1;
            }

            this.size1 = n;
        }

        private int numDisjointSets() {
            System.out.println(size1);
            return size1;
        }

        private boolean find(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return true;
            }
            return false;
        }

        private int root(int b) {
            while (parent[b] != b) {
                parent[b] = parent[parent[b]];
                b = parent[b];
            }
            return b;
        }

        private void union(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return;
            }

            if (size[rootA] < size[rootB]) {
                parent[rootA] = parent[rootB];
                size[rootB] += size[rootA];
            } else {
                parent[rootB] = parent[rootA];
                size[rootA] += size[rootB];
            }
            size1--;
            System.out.println(Arrays.toString(parent));
        }
    }

    private static class SegTree {
        int[] st;
        int[] arr;

        public SegTree(int[] arr) {
            this.arr = arr;
            int size = (int) Math.ceil(Math.log(arr.length) / Math.log(2));
            st = new int[(int) ((2 * Math.pow(2, size)) - 1)];
            buildSegmentTree(1, 0, arr.length - 1);
        }

        //**********JUST CALL THE CONSTRUCTOR, THIS FUNCTION WILL BE CALLED AUTOMATICALLY******
        private void buildSegmentTree(int index, int L, int R) {
            if (L == R) {
                st[index] = arr[L];
                return;
            }

            buildSegmentTree(index * 2, L, (L + R) / 2);
            buildSegmentTree(index * 2 + 1, (L + R) / 2 + 1, R);
//          Replace this line if you want to change the function of the Segment tree.
            st[index] = Math.min(st[index * 2], st[index * 2 + 1]);
        }

        //***********We have to use this function **************
        private int Query(int queL, int queR) {
            return Query1(1, 0, arr.length - 1, queL, queR);
        }

        //This is a helper function.
        //************* DO NOT USE THIS ****************
        private int Query1(int index, int segL, int segR, int queL, int queR) {
            if (queL > segR || queR < segL) {
                return -1;
            }

            if (queL <= segL && queR >= segR) {
                return st[index];
            }

            int ans1 = Query1(index * 2, segL, (segL + segR) / 2, queL, queR);
            int ans2 = Query1(index * 2 + 1, (segL + segR) / 2 + 1, segR, queL, queR);
            if (ans1 == -1) {
                return ans2;
            }

            if (ans2 == -1) {
                return ans1;
            }
//             Segment tree implemented for range minimum query. Change the below line to change the function.
            return Math.min(ans1, ans2);
        }

        private void update(int idx, int val) {
            update1(1, 0, arr.length - 1, idx, val);
        }

        private void update1(int node, int queL, int queR, int idx, int val) {
            // idx - index to be updated in the array
            // node - index to be updated in the seg tree
            if (queL == queR) {
                // Leaf node
                arr[idx] += val;
                st[node] += val;
            } else {
                int mid = (queL + queR) / 2;
                if (queL <= idx && idx <= mid) {
                    // If idx is in the left child, recurse on the left child
                    update1(2 * node, queL, mid, idx, val);
                } else {
                    // if idx is in the right child, recurse on the right child
                    update1(2 * node + 1, mid + 1, queR, idx, val);
                }
                // Internal node will have the min of both of its children
                st[node] = Math.min(st[2 * node], st[2 * node + 1]);
            }
        }

    }

    private static class FastReader {
        InputStream is;

        public FastReader(boolean onlineJudge) {
            is = onlineJudge ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        }

        byte[] inbuf = new byte[1024];
        public int lenbuf = 0, ptrbuf = 0;

        int readByte() {
            if (lenbuf == -1)
                throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0)
                    return -1;
            }
            return inbuf[ptrbuf++];
        }

        boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b))
                ;
            return b;
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        char nextChar() {
            return (char) skip();
        }

        String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        String nextLine() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while ((!isSpaceChar(b) || b == ' ')) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        char[][] nextMatrix(int n, int m) {
            char[][] map = new char[n][];
            for (int i = 0; i < n; i++)
                map[i] = next(m);
            return map;
        }

        int[] nextIntArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        long[] nextLongArray(int n) {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
                a[i] = nextLong();
            return a;
        }

        int[][] next2DInt(int n, int m) {
            int[][] arr = new int[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextIntArray(m);
            }
            return arr;
        }

        long[][] next2DLong(int n, int m) {
            long[][] arr = new long[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLongArray(m);
            }
            return arr;
        }

        int[] shuffle(int[] arr) {
            Random r = new Random();
            for (int i = 1, j; i < arr.length; i++) {
                j = r.nextInt(i);
                arr[i] = arr[i] ^ arr[j];
                arr[j] = arr[i] ^ arr[j];
                arr[i] = arr[i] ^ arr[j];
            }
            return arr;
        }

        int[] uniq(int[] arr) {
            Arrays.sort(arr);
            int[] rv = new int[arr.length];
            int pos = 0;
            rv[pos++] = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if (arr[i] != arr[i - 1]) {
                    rv[pos++] = arr[i];
                }
            }
            return Arrays.copyOf(rv, pos);
        }
    }

}

// package Practice.CF1117;

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class CF1117D {
    static FastReader s;
    static PrintWriter out;
    static String INPUT = "3 2\n";
    static int mod = 1000_000_007;

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
        out = new PrintWriter(System.out);
        s = new FastReader(oj);
        long n = s.nextLong() % mod;
        long m = s.nextLong() % mod;
        long k = n/m;
        long firstTerm = n - m + 1;
        long ans;
        if(k != 1) {
            long a = (k/2) % mod;
            long b = (2% mod * firstTerm% mod) % mod;
            long km = (k % mod) * (m % mod) % mod;
            ans = ((a % mod) * ((b - km + m) % mod) % mod);
        } else {
            ans = firstTerm;
        }
        out.println((ans+1)% mod);
        if (!oj) {
            System.out.println(Arrays.deepToString(new Object[]{System.currentTimeMillis() - time + " ms"}));
        }
        out.flush();
    }

    private static class Maths {
        static ArrayList<Long> printDivisors(long n) {
            // Note that this loop runs till square root
            ArrayList<Long> list = new ArrayList<>();
            for (long i = 1; i <= Math.sqrt(n); i++) {
                if (n % i == 0) {
                    if (n / i == i) {
                        list.add(i);
                    } else {
                        list.add(i);
                        list.add(n / i);
                    }
                }
            }
            return list;
        }

        //    GCD - Using Euclid theorem.
        private static long gcd(long a, long b) {
            if (b == 0) {
                return a;
            }

            return gcd(b, a % b);
        }

        //    Extended euclidean algorithm
//    Used to solve equations of the form ax + by = gcd(a,b)
//    return array [d, a, b] such that d = gcd(p, q), ap + bq = d
        static long[] extendedEuclidean(long p, long q) {
            if (q == 0)
                return new long[]{p, 1, 0};

            long[] vals = extendedEuclidean(q, p % q);
            long d = vals[0];
            long a = vals[2];
            long b = vals[1] - (p / q) * vals[2];
            return new long[]{d, a, b};
        }

        // X ^ y mod p
        static long power(long x, long y, long p) {
            long res = 1;
            x = x % p;

            while (y > 0) {
                if ((y & 1) == 1)
                    res = (res * x) % p;
                y = y >> 1;
                x = (x * x) % p;
            }
            return res;
        }

        // Returns modulo inverse of a
        // with respect to m using extended
        // Euclid Algorithm. Refer below post for details:
        // https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/
        static long inv(long a, long m) {
            long m0 = m, t, q;
            long x0 = 0, x1 = 1;

            if (m == 1)
                return 0;

            // Apply extended Euclid Algorithm
            while (a > 1) {
                q = a / m;
                t = m;
                m = a % m;
                a = t;
                t = x0;
                x0 = x1 - q * x0;
                x1 = t;
            }

            // Make x1 positive
            if (x1 < 0)
                x1 += m0;

            return x1;
        }

        // k is size of num[] and rem[].
        // Returns the smallest number
        // x such that:
        // x % num[0] = rem[0],
        // x % num[1] = rem[1],
        // ..................
        // x % num[k-2] = rem[k-1]
        // Assumption: Numbers in num[] are pairwise
        // coprime (gcd for every pair is 1)
        static long findMinX(long num[], long rem[], long k) {
            int prod = 1;
            for (int i = 0; i < k; i++)
                prod *= num[i];

            int result = 0;
            for (int i = 0; i < k; i++) {
                long pp = prod / num[i];
                result += rem[i] * inv(pp, num[i]) * pp;
            }

            return result % prod;
        }
    }

    private static class BS {
        //  Binary search
        private static int binarySearch(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    return mid;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return -1;
        }

        //    First occurence using binary search
        private static int binarySearchFirstOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    high = mid - 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }

        //    Last occurenece using binary search
        private static int binarySearchLastOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    low = mid + 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }
    }

    private static class arrays {
        // Merge sort
        static void merge(int arr[], int l, int m, int r) {
            int n1 = m - l + 1;
            int n2 = r - m;
            int L[] = new int[n1];
            int R[] = new int[n2];
            for (int i = 0; i < n1; ++i)
                L[i] = arr[l + i];
            for (int j = 0; j < n2; ++j)
                R[j] = arr[m + 1 + j];
            int i = 0, j = 0;
            int k = l;
            while (i < n1 && j < n2) {
                if (L[i] <= R[j]) {
                    arr[k] = L[i];
                    i++;
                } else {
                    arr[k] = R[j];
                    j++;
                }
                k++;
            }

            while (i < n1) {
                arr[k] = L[i];
                i++;
                k++;
            }

            while (j < n2) {
                arr[k] = R[j];
                j++;
                k++;
            }
        }

        static void sort(int arr[], int l, int r) {
            if (l < r) {
                int m = (l + r) / 2;
                sort(arr, l, m);
                sort(arr, m + 1, r);
                merge(arr, l, m, r);
            }
        }

        static void sort(int[] arr) {
            sort(arr, 0, arr.length - 1);
        }
    }

    private static class UnionFindDisjointSet {
        int[] parent;
        int[] size;
        int n;
        int size1;

        public UnionFindDisjointSet(int n) {
            this.n = n;
            this.parent = new int[n];
            this.size = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }

            for (int i = 0; i < n; i++) {
                size[i] = 1;
            }

            this.size1 = n;
        }

        private int numDisjointSets() {
            System.out.println(size1);
            return size1;
        }

        private boolean find(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return true;
            }
            return false;
        }

        private int root(int b) {
            while (parent[b] != b) {
                parent[b] = parent[parent[b]];
                b = parent[b];
            }
            return b;
        }

        private void union(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return;
            }

            if (size[rootA] < size[rootB]) {
                parent[rootA] = parent[rootB];
                size[rootB] += size[rootA];
            } else {
                parent[rootB] = parent[rootA];
                size[rootA] += size[rootB];
            }
            size1--;
            System.out.println(Arrays.toString(parent));
        }
    }

    private static class SegTree {
        int[] st;
        int[] arr;

        public SegTree(int[] arr) {
            this.arr = arr;
            int size = (int) Math.ceil(Math.log(arr.length) / Math.log(2));
            st = new int[(int) ((2 * Math.pow(2, size)) - 1)];
            buildSegmentTree(1, 0, arr.length - 1);
        }

        //**********JUST CALL THE CONSTRUCTOR, THIS FUNCTION WILL BE CALLED AUTOMATICALLY******
        private void buildSegmentTree(int index, int L, int R) {
            if (L == R) {
                st[index] = arr[L];
                return;
            }

            buildSegmentTree(index * 2, L, (L + R) / 2);
            buildSegmentTree(index * 2 + 1, (L + R) / 2 + 1, R);
//          Replace this line if you want to change the function of the Segment tree.
            st[index] = Math.min(st[index * 2], st[index * 2 + 1]);
        }

        //***********We have to use this function **************
        private int Query(int queL, int queR) {
            return Query1(1, 0, arr.length - 1, queL, queR);
        }

        //This is a helper function.
        //************* DO NOT USE THIS ****************
        private int Query1(int index, int segL, int segR, int queL, int queR) {
            if (queL > segR || queR < segL) {
                return -1;
            }

            if (queL <= segL && queR >= segR) {
                return st[index];
            }

            int ans1 = Query1(index * 2, segL, (segL + segR) / 2, queL, queR);
            int ans2 = Query1(index * 2 + 1, (segL + segR) / 2 + 1, segR, queL, queR);
            if (ans1 == -1) {
                return ans2;
            }

            if (ans2 == -1) {
                return ans1;
            }
//             Segment tree implemented for range minimum query. Change the below line to change the function.
            return Math.min(ans1, ans2);
        }

        private void update(int idx, int val) {
            update1(1, 0, arr.length - 1, idx, val);
        }

        private void update1(int node, int queL, int queR, int idx, int val) {
            // idx - index to be updated in the array
            // node - index to be updated in the seg tree
            if (queL == queR) {
                // Leaf node
                arr[idx] += val;
                st[node] += val;
            } else {
                int mid = (queL + queR) / 2;
                if (queL <= idx && idx <= mid) {
                    // If idx is in the left child, recurse on the left child
                    update1(2 * node, queL, mid, idx, val);
                } else {
                    // if idx is in the right child, recurse on the right child
                    update1(2 * node + 1, mid + 1, queR, idx, val);
                }
                // Internal node will have the min of both of its children
                st[node] = Math.min(st[2 * node], st[2 * node + 1]);
            }
        }

    }

    private static class FastReader {
        InputStream is;

        public FastReader(boolean onlineJudge) {
            is = onlineJudge ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        }

        byte[] inbuf = new byte[1024];
        public int lenbuf = 0, ptrbuf = 0;

        int readByte() {
            if (lenbuf == -1)
                throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0)
                    return -1;
            }
            return inbuf[ptrbuf++];
        }

        boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b))
                ;
            return b;
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        char nextChar() {
            return (char) skip();
        }

        String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        String nextLine() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while ((!isSpaceChar(b) || b == ' ')) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        char[][] nextMatrix(int n, int m) {
            char[][] map = new char[n][];
            for (int i = 0; i < n; i++)
                map[i] = next(m);
            return map;
        }

        int[] nextIntArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        long[] nextLongArray(int n) {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
                a[i] = nextLong();
            return a;
        }

        int[][] next2DInt(int n, int m) {
            int[][] arr = new int[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextIntArray(m);
            }
            return arr;
        }

        long[][] next2DLong(int n, int m) {
            long[][] arr = new long[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLongArray(m);
            }
            return arr;
        }

        int[] shuffle(int[] arr) {
            Random r = new Random();
            for (int i = 1, j; i < arr.length; i++) {
                j = r.nextInt(i);
                arr[i] = arr[i] ^ arr[j];
                arr[j] = arr[i] ^ arr[j];
                arr[i] = arr[i] ^ arr[j];
            }
            return arr;
        }

        int[] uniq(int[] arr) {
            Arrays.sort(arr);
            int[] rv = new int[arr.length];
            int pos = 0;
            rv[pos++] = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if (arr[i] != arr[i - 1]) {
                    rv[pos++] = arr[i];
                }
            }
            return Arrays.copyOf(rv, pos);
        }
    }

}

// package Practice.CF1117;

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class CF1117D {
    static FastReader s;
    static PrintWriter out;
    static String INPUT = "3 2\n";
    static int mod = 1000_000_007;
    static long[][] I;

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
        out = new PrintWriter(System.out);
        s = new FastReader(oj);
        long n = s.nextLong();
        int m = s.nextInt();
        long[][] arr = new long[m][m];
        I = new long[m][m];
        arr[m - 1][0] = 1;
        arr[m - 1][m - 1] = 1;
        for (int i = 0; i < m - 1; i++) {
            arr[i][i + 1] = 1;
            I[i][i] = 1;
        }
//        I[0][0] = 1;
        I[m - 1][m - 1] = 1;
        long[][] fArr = new long[m][1];
        for (int i = 0; i < m; i++) {
            fArr[i][0] = 1;
        }
        long[][] ans = mult(exp(arr, n-1), fArr);
        out.println(ans[ans.length - 1][ans[0].length - 1]);

//        out.println((ans.add(BigInteger.ONE)).mod(BigInteger.valueOf(mod)));
        if (!oj) {
            System.out.println(Arrays.deepToString(new Object[]{System.currentTimeMillis() - time + " ms"}));
        }
        out.flush();
    }

    public static long[][] exp(long[][] M, long n)
    {
        if (n == 0) return I;
        if (n == 1) return M;
        long[][] res = exp(M, n/2);
        res = mult(res, res);
        if (n %2 == 0) return res;
        return mult(res, M);
    }

    public static long[][] mult(long[][] p, long[][] q)
    {
        long[][] r = new long[p.length][q[0].length];
        for (int i = 0; i < p.length; i++)
            for (int j = 0; j < q[0].length; j++)
                for (int k = 0; k < q.length; k++)
                {
                    r[i][j] += p[i][k]*q[k][j];
                    r[i][j] %= mod;
                }
        return r;
    }

    private static class Maths {
        static ArrayList<Long> printDivisors(long n) {
            // Note that this loop runs till square root
            ArrayList<Long> list = new ArrayList<>();
            for (long i = 1; i <= Math.sqrt(n); i++) {
                if (n % i == 0) {
                    if (n / i == i) {
                        list.add(i);
                    } else {
                        list.add(i);
                        list.add(n / i);
                    }
                }
            }
            return list;
        }

        //    GCD - Using Euclid theorem.
        private static long gcd(long a, long b) {
            if (b == 0) {
                return a;
            }

            return gcd(b, a % b);
        }

        //    Extended euclidean algorithm
//    Used to solve equations of the form ax + by = gcd(a,b)
//    return array [d, a, b] such that d = gcd(p, q), ap + bq = d
        static long[] extendedEuclidean(long p, long q) {
            if (q == 0)
                return new long[]{p, 1, 0};

            long[] vals = extendedEuclidean(q, p % q);
            long d = vals[0];
            long a = vals[2];
            long b = vals[1] - (p / q) * vals[2];
            return new long[]{d, a, b};
        }

        // X ^ y mod p
        static long power(long x, long y, long p) {
            long res = 1;
            x = x % p;

            while (y > 0) {
                if ((y & 1) == 1)
                    res = (res * x) % p;
                y = y >> 1;
                x = (x * x) % p;
            }
            return res;
        }

        // Returns modulo inverse of a
        // with respect to m using extended
        // Euclid Algorithm. Refer below post for details:
        // https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/
        static long inv(long a, long m) {
            long m0 = m, t, q;
            long x0 = 0, x1 = 1;

            if (m == 1)
                return 0;

            // Apply extended Euclid Algorithm
            while (a > 1) {
                q = a / m;
                t = m;
                m = a % m;
                a = t;
                t = x0;
                x0 = x1 - q * x0;
                x1 = t;
            }

            // Make x1 positive
            if (x1 < 0)
                x1 += m0;

            return x1;
        }

        // k is size of num[] and rem[].
        // Returns the smallest number
        // x such that:
        // x % num[0] = rem[0],
        // x % num[1] = rem[1],
        // ..................
        // x % num[k-2] = rem[k-1]
        // Assumption: Numbers in num[] are pairwise
        // coprime (gcd for every pair is 1)
        static long findMinX(long num[], long rem[], long k) {
            int prod = 1;
            for (int i = 0; i < k; i++)
                prod *= num[i];

            int result = 0;
            for (int i = 0; i < k; i++) {
                long pp = prod / num[i];
                result += rem[i] * inv(pp, num[i]) * pp;
            }

            return result % prod;
        }
    }

    private static class BS {
        //  Binary search
        private static int binarySearch(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    return mid;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return -1;
        }

        //    First occurence using binary search
        private static int binarySearchFirstOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    high = mid - 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }

        //    Last occurenece using binary search
        private static int binarySearchLastOccurence(int[] arr, int ele) {
            int low = 0;
            int high = arr.length - 1;
            int ans = -1;
            while (low <= high) {
                int mid = (low + high) / 2;
                if (arr[mid] == ele) {
                    ans = mid;
                    low = mid + 1;
                } else if (ele < arr[mid]) {
                    high = mid - 1;
                } else {
                    low = mid + 1;
                }
            }
            return ans;
        }
    }

    private static class arrays {
        // Merge sort
        static void merge(int arr[], int l, int m, int r) {
            int n1 = m - l + 1;
            int n2 = r - m;
            int L[] = new int[n1];
            int R[] = new int[n2];
            for (int i = 0; i < n1; ++i)
                L[i] = arr[l + i];
            for (int j = 0; j < n2; ++j)
                R[j] = arr[m + 1 + j];
            int i = 0, j = 0;
            int k = l;
            while (i < n1 && j < n2) {
                if (L[i] <= R[j]) {
                    arr[k] = L[i];
                    i++;
                } else {
                    arr[k] = R[j];
                    j++;
                }
                k++;
            }

            while (i < n1) {
                arr[k] = L[i];
                i++;
                k++;
            }

            while (j < n2) {
                arr[k] = R[j];
                j++;
                k++;
            }
        }

        static void sort(int arr[], int l, int r) {
            if (l < r) {
                int m = (l + r) / 2;
                sort(arr, l, m);
                sort(arr, m + 1, r);
                merge(arr, l, m, r);
            }
        }

        static void sort(int[] arr) {
            sort(arr, 0, arr.length - 1);
        }
    }

    private static class UnionFindDisjointSet {
        int[] parent;
        int[] size;
        int n;
        int size1;

        public UnionFindDisjointSet(int n) {
            this.n = n;
            this.parent = new int[n];
            this.size = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }

            for (int i = 0; i < n; i++) {
                size[i] = 1;
            }

            this.size1 = n;
        }

        private int numDisjointSets() {
            System.out.println(size1);
            return size1;
        }

        private boolean find(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return true;
            }
            return false;
        }

        private int root(int b) {
            while (parent[b] != b) {
                parent[b] = parent[parent[b]];
                b = parent[b];
            }
            return b;
        }

        private void union(int a, int b) {
            int rootA = root(a);
            int rootB = root(b);
            if (rootA == rootB) {
                return;
            }

            if (size[rootA] < size[rootB]) {
                parent[rootA] = parent[rootB];
                size[rootB] += size[rootA];
            } else {
                parent[rootB] = parent[rootA];
                size[rootA] += size[rootB];
            }
            size1--;
            System.out.println(Arrays.toString(parent));
        }
    }

    private static class SegTree {
        int[] st;
        int[] arr;

        public SegTree(int[] arr) {
            this.arr = arr;
            int size = (int) Math.ceil(Math.log(arr.length) / Math.log(2));
            st = new int[(int) ((2 * Math.pow(2, size)) - 1)];
            buildSegmentTree(1, 0, arr.length - 1);
        }

        //**********JUST CALL THE CONSTRUCTOR, THIS FUNCTION WILL BE CALLED AUTOMATICALLY******
        private void buildSegmentTree(int index, int L, int R) {
            if (L == R) {
                st[index] = arr[L];
                return;
            }

            buildSegmentTree(index * 2, L, (L + R) / 2);
            buildSegmentTree(index * 2 + 1, (L + R) / 2 + 1, R);
//          Replace this line if you want to change the function of the Segment tree.
            st[index] = Math.min(st[index * 2], st[index * 2 + 1]);
        }

        //***********We have to use this function **************
        private int Query(int queL, int queR) {
            return Query1(1, 0, arr.length - 1, queL, queR);
        }

        //This is a helper function.
        //************* DO NOT USE THIS ****************
        private int Query1(int index, int segL, int segR, int queL, int queR) {
            if (queL > segR || queR < segL) {
                return -1;
            }

            if (queL <= segL && queR >= segR) {
                return st[index];
            }

            int ans1 = Query1(index * 2, segL, (segL + segR) / 2, queL, queR);
            int ans2 = Query1(index * 2 + 1, (segL + segR) / 2 + 1, segR, queL, queR);
            if (ans1 == -1) {
                return ans2;
            }

            if (ans2 == -1) {
                return ans1;
            }
//             Segment tree implemented for range minimum query. Change the below line to change the function.
            return Math.min(ans1, ans2);
        }

        private void update(int idx, int val) {
            update1(1, 0, arr.length - 1, idx, val);
        }

        private void update1(int node, int queL, int queR, int idx, int val) {
            // idx - index to be updated in the array
            // node - index to be updated in the seg tree
            if (queL == queR) {
                // Leaf node
                arr[idx] += val;
                st[node] += val;
            } else {
                int mid = (queL + queR) / 2;
                if (queL <= idx && idx <= mid) {
                    // If idx is in the left child, recurse on the left child
                    update1(2 * node, queL, mid, idx, val);
                } else {
                    // if idx is in the right child, recurse on the right child
                    update1(2 * node + 1, mid + 1, queR, idx, val);
                }
                // Internal node will have the min of both of its children
                st[node] = Math.min(st[2 * node], st[2 * node + 1]);
            }
        }

    }

    private static class FastReader {
        InputStream is;

        public FastReader(boolean onlineJudge) {
            is = onlineJudge ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        }

        byte[] inbuf = new byte[1024];
        public int lenbuf = 0, ptrbuf = 0;

        int readByte() {
            if (lenbuf == -1)
                throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0)
                    return -1;
            }
            return inbuf[ptrbuf++];
        }

        boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b))
                ;
            return b;
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        char nextChar() {
            return (char) skip();
        }

        String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        String nextLine() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while ((!isSpaceChar(b) || b == ' ')) { // when nextLine, (isSpaceChar(b) && b != ' ')
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
                ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        char[][] nextMatrix(int n, int m) {
            char[][] map = new char[n][];
            for (int i = 0; i < n; i++)
                map[i] = next(m);
            return map;
        }

        int[] nextIntArray(int n) {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        long[] nextLongArray(int n) {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
                a[i] = nextLong();
            return a;
        }

        int[][] next2DInt(int n, int m) {
            int[][] arr = new int[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextIntArray(m);
            }
            return arr;
        }

        long[][] next2DLong(int n, int m) {
            long[][] arr = new long[n][];
            for (int i = 0; i < n; i++) {
                arr[i] = nextLongArray(m);
            }
            return arr;
        }

        int[] shuffle(int[] arr) {
            Random r = new Random();
            for (int i = 1, j; i < arr.length; i++) {
                j = r.nextInt(i);
                arr[i] = arr[i] ^ arr[j];
                arr[j] = arr[i] ^ arr[j];
                arr[i] = arr[i] ^ arr[j];
            }
            return arr;
        }

        int[] uniq(int[] arr) {
            Arrays.sort(arr);
            int[] rv = new int[arr.length];
            int pos = 0;
            rv[pos++] = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if (arr[i] != arr[i - 1]) {
                    rv[pos++] = arr[i];
                }
            }
            return Arrays.copyOf(rv, pos);
        }
    }

}