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

public class F implements Runnable {
	public static void main (String[] args) {new Thread(null, new F(), "_cf", 1 << 28).start();}

	long MOD = (long)1e9+7;

	public void run() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("Go!");

		int n = fs.nextInt();
		int k = fs.nextInt();
		if(k == 0) {
			System.out.println(n);
			return;
		}

		long[] ys = new long[k+5];
		for(int i = 0; i < ys.length; i++) {
			ys[i] = power(i, k);
			if(i > 0) ys[i] = (ys[i-1] + ys[i]) % MOD;
		}

		if(n <= k) {
			System.out.println(ys[n]);
		}
		else {
			System.out.println(interpolate(ys, n));
		}

		out.close();
	}

	// Given k+1 (x,y) coordinates of a k-degree polynomial, allows you to query any x //%
	// O(k) interpolation given the ys of x=0,1,2,..,k //%
	long interpolate(long[] ys, long x) {
		int n = ys.length;
		long[] ifa = new long[n], b = new long[n];
		long f = 1, y = 0, a = 1;
		for (int i = 1; i < n; i++)
			f = f * i % MOD;
		ifa[n - 1] = mi(f);
		for (int i = n - 1; i >= 1; i--)
			ifa[i - 1] = ifa[i] * i % MOD;
		b[n - 1] = 1;
		for (int i = n - 1; i >= 1; i--)
			b[i - 1] = b[i] * (x - i) % MOD;
		for (int i = 0; i < n; i++) {
			long t = (a * b[i] % MOD) * ys[i] % MOD;
			t = (t * ifa[i] % MOD) * ifa[n - 1 - i] % MOD;
			y += ((n - i) & 1) == 0 ? -t : t;
			a = a * (x - i) % MOD;
		}
		return ((y % MOD) + MOD) % MOD;
	}
	// O(k^2) interpolation given any (x,y) pairs //%
	long interpolate(long[] xs, long[] ys, long x) {
		int n = ys.length;  long y = 0;
		for (int i = 0; i < n; i++) {
			long t = ys[i];
			for (int j = 0; j < n; j++)
				if (i != j) t = (t * (x - xs[j]) % MOD) * mi(xs[i] - xs[j]) % MOD;
			y += t;
		}
		return ((y % MOD) + MOD) % MOD;
	}

	long mi(long x) {
		return power(x, MOD - 2);
	}

	long power(long base, long expo) {
		base %= MOD;
		long x = base;
		long res = 1;
		while(expo > 0) {
			if((expo & 1L) > 0) {
				res = res * x % MOD;
			}
			x = x * x % MOD;
			expo /= 2;
		}
		return res;
	}

	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.OutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
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 << 29);
        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);
            FTheSumOfTheKThPowers solver = new FTheSumOfTheKThPowers();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class FTheSumOfTheKThPowers {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int mod = (int) (1e9 + 7);
            int n = in.readInt();
            int k = in.readInt();

            if (k == 0) {
                out.println(n);
                return;
            }

            Power power = new Power(mod);
            int[] y = new int[k + 2];
            for (int i = 0; i <= k + 1; i++) {
                y[i] = power.pow(i, k);
            }
            for (int i = 1; i <= k + 1; i++) {
                y[i] = DigitUtils.modplus(y[i - 1], y[i], mod);
            }

            ModContinuousInterpolation interpolation = new ModContinuousInterpolation(0, y, mod);

            int ans = interpolation.interpolate(n);
            out.println(ans);
        }

    }

    static interface InverseNumber {
    }

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

        public FastOutput append(CharSequence csq) {
            cache.append(csq);
            return this;
        }

        public FastOutput append(CharSequence csq, int start, int end) {
            cache.append(csq, start, end);
            return this;
        }

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

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

        public FastOutput append(char c) {
            cache.append(c);
            return this;
        }

        public FastOutput append(int c) {
            cache.append(c);
            return this;
        }

        public FastOutput println(int c) {
            return append(c).println();
        }

        public FastOutput println() {
            cache.append(System.lineSeparator());
            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 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;
        }

    }

    static class DigitUtils {
        private DigitUtils() {
        }

        public static int negate(int x, int mod) {
            return x == 0 ? 0 : mod - x;
        }

        public static int modsub(int a, int b, int mod) {
            int ans = a - b;
            if (ans < 0) {
                ans += mod;
            }
            return ans;
        }

        public static int modplus(int a, int b, int mod) {
            int ans = a + b;
            if (ans >= mod) {
                ans -= mod;
            }
            return ans;
        }

    }

    static class Power implements InverseNumber {
        int mod;

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

        public Power(int mod) {
            this(new Modular(mod));
        }

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

    }

    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 String toString() {
            return "mod " + m;
        }

    }

    static class Factorial {
        int[] fact;
        int[] inv;
        int mod;

        public Factorial(int[] fact, int[] inv, int mod) {
            this.mod = mod;
            this.fact = fact;
            this.inv = inv;
            fact[0] = inv[0] = 1;
            int n = Math.min(fact.length, mod);
            for (int i = 1; i < n; i++) {
                fact[i] = i;
                fact[i] = (int) ((long) fact[i] * fact[i - 1] % mod);
            }
            inv[n - 1] = BigInteger.valueOf(fact[n - 1]).modInverse(BigInteger.valueOf(mod)).intValue();
            for (int i = n - 2; i >= 1; i--) {
                inv[i] = (int) ((long) inv[i + 1] * (i + 1) % mod);
            }
        }

        public Factorial(int limit, int mod) {
            this(new int[limit + 1], new int[limit + 1], mod);
        }

        public int invFact(int n) {
            return inv[n];
        }

    }

    static class ModContinuousInterpolation {
        private int x0;
        private int[] y;
        private int mod;
        private int[] pre;
        private int[] post;
        private Factorial fact;

        public ModContinuousInterpolation(int x0, int[] y, int mod) {
            this(x0, y, mod, new Factorial(y.length - 1, mod));
        }

        public ModContinuousInterpolation(int x0, int[] y, int mod, Factorial fact) {
            this.x0 = x0;
            this.y = y;
            this.mod = mod;

            int n = y.length;
            pre = new int[n];
            post = new int[n];
            this.fact = fact;
        }

        public int interpolate(int x) {
            x = DigitUtils.modsub(x, x0, mod);
            int n = y.length;
            if (x < n) {
                return y[x];
            }

            for (int i = 0; i < n; i++) {
                pre[i] = post[i] = DigitUtils.modsub(x, i, mod);
            }
            for (int i = 1; i < n; i++) {
                pre[i] = (int) ((long) pre[i - 1] * pre[i] % mod);
                post[n - i - 1] = (int) ((long) post[n - i - 1] * post[n - i] % mod);
            }

            long sum = 0;
            for (int i = 0; i < n; i++) {
                int local = (int) ((long) y[i] * fact.invFact(i) % mod * fact.invFact(n - 1 - i) % mod);
                if (i > 0) {
                    local = (int) ((long) local * pre[i - 1] % mod);
                }
                if (i + 1 < n) {
                    local = (int) ((long) local * post[i + 1] % mod);
                }
                if (((n - 1 - i) & 1) == 1) {
                    local = DigitUtils.negate(local, mod);
                }
                sum += local;
            }

            return (int) (sum % mod);
        }

    }
}

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

public class Main {
	static final int MOD = 1000000007;

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

	public static int power(int basic, int times) {
		int ret = 1;
		while(times > 0) {
			if((times & 1) == 1) ret = mul(ret, basic);
			basic = mul(basic, basic);
			times >>= 1;
		}
		return ret;
	}

	public static Integer[] extGcd(Integer a, Integer b) {
		Integer [] ret = new Integer[3];
		if(b == 0) {
			ret[0] = Integer.valueOf(a.intValue());
			ret[1] = Integer.valueOf(1);
			ret[2] = Integer.valueOf(0);
		} else {
			Integer [] tmp = extGcd(b, a % b);
			Integer g = tmp[0], ta = tmp[2], tb = tmp[1] - a / b * tmp[2];
			if(ta < 0) {
				Integer t = ta / (b / g);
				ta -= t * (b / g);
				tb += t * (a / g);
			}
			if(ta < 0) {
				ta += b / g;
				tb -= a / g;
			}
			ret[0] = g;
			ret[1] = ta;
			ret[2] = tb;
		}
		return ret;
	}

	public static int inv(int x) {
//		0-> gcd   1->ta    2->tb
//		Integer [] results = extGcd(x, MOD);
//		return results[1];
		return power(x, MOD - 2);
	}

	public static int solve(int n, int m) {
//		System.out.println(n + " " + m);

		int [] f = new int[m + 3];
		f[0] = 0;
		for(int i = 1; i <= m + 2; i++) {
			f[i] = f[i - 1] + power(i, m);
			if(f[i] >= MOD) f[i] -= MOD;
		}
//		System.out.println(power(Integer.valueOf(2), Integer.valueOf(100)));

//		for(Integer i = Integer.valueOf(1); i <= m + 2; i++)
//			System.out.print(f[i] + " ");
//		System.out.println("");

		if(n <= m + 2) return f[n];

		int [] lagrange = new int[m + 3];
		int [] fact = new int[m + 3];
		fact[0] = 1;
		for(int i = 1; i <= m + 2; i++)
			fact[i] = mul(fact[i - 1], i);
		for(int i = 1; i <= m + 2; i++) {
			lagrange[i] = f[i];
			lagrange[i] = mul(lagrange[i], inv(mul(fact[i - 1], fact[m + 2 - i])));
			if(((m + 2 - i) & 1) == 1)
				lagrange[i] = MOD - lagrange[i];
//			System.out.print(lagrange[i] + " ");
		}
//		System.out.println("");

		int fullDenominator = 1;
		for(int i = 1; i <= m + 2; i++)
			fullDenominator = mul(fullDenominator, n - i);
//		System.out.println(fullDenominator);

		Integer ret = Integer.valueOf(0);
		for(int i = 1; i <= m + 2; i++) {
			int denominator = mul(fullDenominator, inv(n - i));
//			System.out.print(denominator + " ");
			ret = ret + mul(denominator, lagrange[i]);
			if(ret >= MOD) ret -= MOD;
		}
		return ret;
	}

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

		Scanner reader = new Scanner(System.in);
		Integer n = new Integer(reader.nextInt());
		Integer k = new Integer(reader.nextInt());

		Integer ans = solve(n, k);

		System.out.println(ans);

		reader.close();
	}
}

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

// Educational Codeforces Round 7
// The Sum of the k-th Powers
public class Problem_622_F {
    public static final int MOD = 1000000007;

    public static void main(String[] args)
    {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        PrintWriter out = new PrintWriter(outputStream);
        Problem_622_F solver = new Problem_622_F();
        solver.solve(1, new InputStreamReader(inputStream), out);
        out.close();
    }

    int xx;
    int yy;

    int gcd(int a, int b)
    {
      if (a == 0) {
        xx = 0;
        yy = 1;
        return b;
      }
      int x, y, g = gcd(b % a, a);

      x = yy - b / a * xx;
      y = xx;

      xx = x;
      yy = y;

      return g;
    }

    int inv(int a)
    {
      gcd(a, MOD);
      return normal(xx);
    }

    int add(int a, int b)
    {
      return (a + b) % MOD;
    }

    int mul(int a, int b)
    {
      return (int)((a * 1L * b) % MOD);
    }

    int _div(int a, int b)
    {
      return mul(a, inv(b));
    }

    int normal(int a)
    {
      a = a % MOD;
      if(a < 0) a += MOD;
      return a;
    }

    int binPow(int a, int b)
    {
      int res = 1;

      while(b > 0) {
        if((b & 1) != 0) res = mul(res, a);
        a = mul(a, a);
        b >>= 1;
      }
      return res;
    }

    int calc(ArrayList<Integer> y, int x)
    {
      int res = 0;
      int k = 1;
      for(int j = 1; j < y.size(); j++) {
        k = mul(k, normal(x - j));
        k = _div(k, normal(0 - j));
      }
      for(int i = 0; i < y.size(); i++) {
        res = add(res, mul(y.get(i), k));
        if(i + 1 >= y.size()) break;
        k = mul(k, _div(normal(x - i), normal(x - (i + 1))));
        k = mul(k, _div(normal(i - (y.size() - 1)), normal(i + 1)));
      }
      return res;
    }

    public void solve(int test, Reader input, PrintWriter out)
    {
        MyScanner in = new MyScanner(input);

        int n = in.nextInt();
        int k = in.nextInt();

        ArrayList<Integer> y = new ArrayList<>();

        int sum = 0;
        y.add(sum);
        for(int i = 0; i < k + 1; i++) {
          sum = add(sum, binPow(i + 1, k));
          y.add(sum);
        }
        int res = 0;
        if(n < y.size()) res = y.get(n);
        else res = calc(y, n);
        out.println(res);
    }

    //-----------MyScanner class for faster input----------
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;

        public MyScanner(Reader reader) {
            br = new BufferedReader(reader);
        }

        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());
        }

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

        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.math.*;
import java.io.*;

public class CF662F {
	long inv(long x) { return exp(x, MOD - 2, MOD); }
	long exp(long b, long e, long m) {
		if(e == 0) return 1;
		long r = exp(b, e / 2, m);
		if((e & 1) == 0) return r * r % MOD;
		return r * r % m * b % m;
	}
	long interpolate(long[] ys, long x) {
		int n = ys.length;
		long[] ifa = new long[n], b = new long[n];
		long f = 1, y = 0, a = 1;
		for(int i = 1 ; i < n ; i++)
			f = f * i % MOD;
		ifa[n - 1] = inv(f);
		for(int i = n - 1 ; i >= 1 ; i--)
			ifa[i - 1] = ifa[i] * i % MOD;
		b[n - 1] = 1;
		for(int i = n - 1 ; i >= 1 ; i--)
			b[i - 1] = b[i] * (x - i) % MOD;
		for(int i = 0 ; i < n ; i++) {
			long t = (a * b[i] % MOD) * ys[i] % MOD;
			t = (t * ifa[i] % MOD) * ifa[n - 1 - i] % MOD;
			y += ((n - i) & 1) == 0 ? -t : t;
			a = a * (x - i) % MOD;
		}
		return ((y % MOD) + MOD) % MOD;
	}
	final int MOD = (int) 1e9 + 7;
	public CF662F() {
		FS scan = new FS();
		int n = scan.nextInt(), k = scan.nextInt();
		long[] ys = new long[1111111];
		long sum = 0;
		for(int i = 1 ; i < 1111111 ; i++) {
			sum += exp(i, k, MOD);
			sum %= MOD;
			ys[i] = sum;
		}
		System.out.println(interpolate(ys, n));
	}
	class FS {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer("");
		public String next() {
			while (!st.hasMoreTokens()) {
				try { st = new StringTokenizer(br.readLine()); }
				catch (Exception e) { e.printStackTrace(); }
			}
			return st.nextToken();
		}
		public int nextInt() { return Integer.parseInt(next()); }
	}
	public static void main(String[] args) { new CF662F(); }
}

//package educational.round07;
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 FX {
	InputStream is;
	PrintWriter out;
	String INPUT = "";
	int mod = 1000000007;

	void solve()
	{
		int n = ni(), K = ni();
		long[] vals = new long[K+3];
		for(int i = 1;i <= K+2;i++){
			vals[i] = pow(i, K, mod);
		}
		if(n <= K+2){
			long s = 0;
			for(int i = 1;i <= n;i++){
				s += vals[i];
			}
			out.println(s%mod);
		}else{
			for(int i = 2;i <= K+2;i++){
				vals[i] += vals[i-1];
				if(vals[i] >= mod)vals[i] -= mod;
			}
			int[][] fif = enumFIF(K+3, mod);
			long mul = 1;
			for(int i = 1;i <= K+2;i++){
				mul = mul * (n-i)%mod;
			}
			long s = 0;
			long sig = 1;
			long big = 8L*mod*mod;
			for(int i = K+2;i >= 1;i--){
				s += invl(n-i, mod) * fif[1][i-1] % mod * fif[1][K+2-i] % mod * vals[i] * sig;
				if(s >= big)s -= big;
				if(s <= -big)s += big;
				sig = -sig;
			}
			s %= mod;
			if(s < 0)s += mod;
			s = s * mul % mod;
			out.println(s);
		}
	}

	public static long pow(long a, long n, long mod) {
		//		a %= mod;
		long ret = 1;
		int x = 63 - Long.numberOfLeadingZeros(n);
		for (; x >= 0; x--) {
			ret = ret * ret % mod;
			if (n << 63 - x < 0)
				ret = ret * a % mod;
		}
		return ret;
	}

	public static long invl(long a, long mod) {
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		return p < 0 ? p + mod : p;
	}

	public static int[][] enumFIF(int n, int mod) {
		int[] f = new int[n + 1];
		int[] invf = new int[n + 1];
		f[0] = 1;
		for (int i = 1; i <= n; i++) {
			f[i] = (int) ((long) f[i - 1] * i % mod);
		}
		long a = f[n];
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		invf[n] = (int) (p < 0 ? p + mod : p);
		for (int i = n - 1; i >= 0; i--) {
			invf[i] = (int) ((long) invf[i + 1] * (i + 1) % mod);
		}
		return new int[][] { f, invf };
	}

	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 FX().run(); }

	private byte[] inbuf = new byte[1024];
	private 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)); }
}

//package que_a;

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

public class utkarsh {

    InputStream is;
    PrintWriter out;

    long mod = (long) (1e9 + 7), inf = (long) (8e18);
    boolean SHOW_TIME, debug;

    long fact[], inv[];

    void getF(int n) {
        fact = new long[n];
        inv = new long[n];
        fact[0] = fact[1] = 1;
        inv[0] = inv[1] = 1;
        for(int i = 2; i < n; i++) {
            fact[i] = (fact[i-1] * i) % mod;
        }
        inv[n-1] = mp(fact[n-1], mod-2);
        for(int i = n-2; i > 1; i--) {
            inv[i] = (inv[i+1] * (i+1)) % mod;
        }
    }

    void solve() {
        //Enter code here utkarsh
        //SHOW_TIME = true;
	//debug = true;
        int n = ni(), k = ni();
        long ans[] = new long[k + 3];
        for(int i = 1; i < k+3; i++) {
            ans[i] = ans[i-1] + mp(i, k);
            if(ans[i] >= mod)   ans[i] -= mod;
        }
        if(n < k+3)   out.println(ans[n] % mod);
        else {
            getF(k+3);

            long s = 0;
            int p = 1;
            inf = mod * mod;
            for(int i = k+2; i >= 1; i--) {
                s += mp(n-i, mod-2) * inv[i-1] % mod * inv[k+2-i] % mod * ans[i] * p;
                if(s >= inf)    s -= inf;
                if(s <= -inf)    s += inf;
                p = -p;
            }
            s %= mod;
            if(s < 0)   s += mod;
            long m = 1;
            for(int i = 1; i < k+3; i++) {
                m = m * (n-i) % mod;
            }
            out.println(s * m % mod);
        }
    }

    long mp(long b, long e) {
        long r = 1;
        while(e > 0) {
            if((e&1) == 1)  r = (r * b) % mod;
            b = (b * b) % mod;
            e >>= 1;
        }
        return r;
    }

    //---------- I/O Template ----------

    public static void main(String[] args) { new utkarsh().run(); }
    void run() {
        is = System.in;
        out = new PrintWriter(System.out);
        long start = System.currentTimeMillis();
        solve();
        long end = System.currentTimeMillis();
        if(SHOW_TIME) out.println("\n" + (end - start) + " ms");
        out.flush();
    }

    byte input[] = new byte[1024];
    int len = 0, ptr = 0;

    int readByte() {
        if(ptr >= len) { ptr = 0;
            try { len = is.read(input); }
            catch(IOException e) { throw new InputMismatchException(); }
            if(len <= 0) { return -1; }
        } return input[ptr++];
    }
    boolean isSpaceChar(int c) { return !( c >= 33 && c <= 126 ); }
    int skip() {
        int b = readByte();
        while(b != -1 && isSpaceChar(b)) { b = readByte(); }
        return b;
    }

    char nc() { return (char)skip(); }
    String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while(!isSpaceChar(b)) { sb.appendCodePoint(b); b = readByte(); }
        return sb.toString();
    }
    String nLine() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while( !(isSpaceChar(b) && b != ' ') ) { sb.appendCodePoint(b); b = readByte(); }
        return sb.toString();
    }
    int ni() {
        int n = 0, b = readByte();
        boolean minus = false;
        while(b != -1 && !( (b >= '0' && b <= '9') || b == '-')) { b = readByte(); }
        if(b == '-') { minus = true; b = readByte(); }
        if(b == -1) { return -1; }  //no input
        while(b >= '0' && b <= '9') { n = n * 10 + (b - '0'); b = readByte(); }
        return minus ? -n : n;
    }
    long nl() {
        long n = 0L;    int b = readByte();
        boolean minus = false;
        while(b != -1 && !( (b >= '0' && b <= '9') || b == '-')) { b = readByte(); }
        if(b == '-') { minus = true; b = readByte(); }
        while(b >= '0' && b <= '9') { n = n * 10 + (b - '0'); b = readByte(); }
        return minus ? -n : n;
    }

    double nd() { return Double.parseDouble(ns()); }
    float nf() { return Float.parseFloat(ns()); }
    int[] na(int n) {
        int a[] = new int[n];
        for(int i = 0; i < n; i++) { a[i] = ni(); }
        return a;
    }
    char[] ns(int n) {
        char c[] = new char[n];
        int i, b = skip();
        for(i = 0; i < n; i++) {
            if(isSpaceChar(b)) { break; }
            c[i] = (char)b; b = readByte();
        } return i == n ? c : Arrays.copyOf(c,i);
    }
}

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

public class Main {
	static final Integer MOD = Integer.valueOf(1000000007);

	public static Integer mul(Integer x, Integer y) {
		Long ret = Long.valueOf(x.intValue());
		ret = (ret * y) % MOD;
		return Integer.valueOf(ret.intValue());
	}

	public static int mul(int x, int y) {
		long ret = x;
		ret *= y;
		ret %= 1000000007;
		return (int) ret;
	}

	public static Integer power(Integer a, Integer b) {
		int basic = a.intValue(), times = b.intValue();
		int ret = 1;
		while(times > 0) {
			if((times & 1) == 1) ret = mul(ret, basic);
			basic = mul(basic, basic);
			times >>= 1;
		}
		return Integer.valueOf(ret);
	}

	public static Integer[] extGcd(Integer a, Integer b) {
		Integer [] ret = new Integer[3];
		if(b == 0) {
			ret[0] = Integer.valueOf(a.intValue());
			ret[1] = Integer.valueOf(1);
			ret[2] = Integer.valueOf(0);
		} else {
			Integer [] tmp = extGcd(b, a % b);
			Integer g = tmp[0], ta = tmp[2], tb = tmp[1] - a / b * tmp[2];
			if(ta < 0) {
				Integer t = ta / (b / g);
				ta -= t * (b / g);
				tb += t * (a / g);
			}
			if(ta < 0) {
				ta += b / g;
				tb -= a / g;
			}
			ret[0] = g;
			ret[1] = ta;
			ret[2] = tb;
		}
		return ret;
	}

	public static Integer inv(Integer x) {
//		0-> gcd   1->ta    2->tb
//		Integer [] results = extGcd(x, MOD);
//		return results[1];
		return power(x, MOD - 2);
	}

	public static Integer solve(Integer n, Integer m) {
		long start = System.currentTimeMillis();
//		System.out.println(n + " " + m);

		Integer [] f = new Integer[m + 3];
		f[0] = Integer.valueOf(0);
		for(int i = 1; i <= m + 2; i++) {
			f[i] = Integer.valueOf(f[i - 1] + power(i, m));
			if(f[i] >= MOD) f[i] -= MOD;
		}
//		System.out.println(power(Integer.valueOf(2), Integer.valueOf(100)));

//		for(Integer i = Integer.valueOf(1); i <= m + 2; i++)
//			System.out.print(f[i] + " ");
//		System.out.println("");

		if(n <= m + 2) return f[n];

		Integer [] lagrange = new Integer[m + 3];
		Integer [] fact = new Integer[m + 3];
		fact[0] = Integer.valueOf(1);
		for(int i = 1; i <= m + 2; i++)
			fact[i] = mul(fact[i - 1].intValue(), i);
		for(int i = 1; i <= m + 2; i++) {
			lagrange[i] = f[i];
			lagrange[i] = mul(lagrange[i], inv(mul(fact[i - 1], fact[m + 2 - i])));
			if(((m + 2 - i) & 1) == 1)
				lagrange[i] = MOD - lagrange[i];
//			System.out.print(lagrange[i] + " ");
		}
//		System.out.println("");

		Integer fullDenominator = Integer.valueOf(1);
		for(int i = 1; i <= m + 2; i++)
			fullDenominator = mul(fullDenominator.intValue(), n - i);
//		System.out.println(fullDenominator);

		Integer ret = Integer.valueOf(0);
		for(int i = 1; i <= m + 2; i++) {
			Integer denominator = Integer.valueOf(mul(fullDenominator, inv(n - i)));
//			System.out.print(denominator + " ");
			ret = ret + mul(denominator, lagrange[i]);
			if(ret >= MOD) ret -= MOD;
		}
		long end = System.currentTimeMillis();
		System.out.println(end - start);
		return ret;
	}

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

		Scanner reader = new Scanner(System.in);
		Integer n = new Integer(reader.nextInt());
		Integer k = new Integer(reader.nextInt());

		Integer ans = solve(n, k);

		System.out.println(ans);

		reader.close();
	}
}

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

public class Main {
	static final Integer N = 1000010, MOD = new Integer(1000000009);

	public static Integer mul(Integer x, Integer y) {
		Long ret = new Long(x.intValue());
		ret = (ret * y) % MOD;
		return Integer.valueOf(ret.intValue());
	}

	public static Integer power(Integer basic, Integer times) {
		Integer ret = Integer.valueOf(1);
		while(times > 0) {
			if((times & 1) == 1)  ret = mul(ret, basic);
			basic = mul(basic, basic);
			times >>= 1;
		}
		return ret;
	}

	public static Integer[] extGcd(Integer a, Integer b) {
		Integer [] ret = new Integer[3];
		if(b == 0) {
			ret[0] = Integer.valueOf(a.intValue());
			ret[1] = Integer.valueOf(1);
			ret[2] = Integer.valueOf(0);
		} else {
			Integer [] tmp = extGcd(b, a % b);
			Integer g = tmp[0], ta = tmp[2], tb = tmp[1] - a / b * tmp[2];
			if(ta < 0) {
				Integer t = ta / (b / g);
				ta -= t * (b / g);
				tb += t * (a / g);
			}
			if(ta < 0) {
				ta += b / g;
				tb -= a / g;
			}
			ret[0] = g;
			ret[1] = ta;
			ret[2] = tb;
		}
		return ret;
	}

	public static Integer inv(Integer x) {
//		0-> gcd   1->ta    2->tb
		Integer [] results = extGcd(x, MOD);
		return results[1];
	}

	public static Integer solve(Integer n, Integer m) {
//		System.out.println(n + " " + m);

		Integer [] f = new Integer[m + 3];
		f[0] = Integer.valueOf(0);
		for(Integer i = Integer.valueOf(1); i <= m + 2; i++)
			f[i] = new Integer((f[i - 1] + power(i, m)) % MOD);

		for(Integer i = Integer.valueOf(1); i <= m + 2; i++)
//			System.out.print(f[i] + " ");
//		System.out.println("");

		if(n <= m + 2) return f[n];

		Integer [] lagrange = new Integer[m + 3];
		Integer [] fact = new Integer[m + 3];
		fact[0] = Integer.valueOf(1);
		for(Integer i = Integer.valueOf(1); i <= m + 2; i++)
			fact[i] = mul(fact[i - 1], i);
		for(Integer i = Integer.valueOf(1); i <= m + 2; i++) {
			lagrange[i] = f[i];
			lagrange[i] = mul(lagrange[i], inv(mul(fact[i - 1], fact[m + 2 - i])));
			if(((m + 2 - i) & 1) == 1)
				lagrange[i] = MOD - lagrange[i];
//			System.out.print(lagrange[i] + " ");
		}
//		System.out.println("");

		Integer fullDenominator = Integer.valueOf(1);
		for(Integer i = Integer.valueOf(1); i <= m + 2; i++)
			fullDenominator = mul(fullDenominator, n - i);
//		System.out.println(fullDenominator);

		Integer ret = Integer.valueOf(0);
		for(Integer i = Integer.valueOf(1); i <= m + 2; i++) {
			Integer denominator = Integer.valueOf(mul(fullDenominator, inv(n - i)));
//			System.out.print(denominator + " ");
			ret = (ret + mul(denominator, lagrange[i])) % MOD;
		}
		return ret;
	}

	public static void main(String[] args) throws IOException {
		Scanner reader = new Scanner(System.in);
		Integer n = new Integer(reader.nextInt());
		Integer k = new Integer(reader.nextInt());

		Integer ans = solve(n, k);

		System.out.println(ans);

		reader.close();
	}
}

//package que_a;

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

public class utkarsh {

    InputStream is;
    PrintWriter out;

    long mod = (long) (1e9 + 7), inf = (long) (8e18);
    boolean SHOW_TIME, debug;

    long fact[], inv[];

    void getF(int n) {
        fact = new long[n];
        inv = new long[n];
        fact[0] = fact[1] = 1;
        inv[0] = inv[1] = 1;
        for(int i = 2; i < n; i++) {
            fact[i] = (fact[i-1] * i) % mod;
            inv[i] = mp(fact[i], mod - 2);
        }
    }

    void solve() {
        //Enter code here utkarsh
        //SHOW_TIME = true;
	//debug = true;
        int n = ni(), k = ni();
        long ans[] = new long[k + 3];
        for(int i = 1; i < k+3; i++) {
            ans[i] = ans[i-1] + mp(i, k);
            if(ans[i] >= mod)   ans[i] -= mod;
        }
        if(n < k+3)   out.println(ans[n] % mod);
        else {
            getF(k+3);

            long s = 0;
            int p = 1;
            for(int i = k+2; i >= 1; i--) {
                s += mp(n-i, mod-2) * inv[i-1] % mod * inv[k+2-i] % mod * ans[i] * p;
                if(s >= inf)    s -= inf;
                if(s <= -inf)    s += inf;
                p = -p;
            }
            s %= mod;
            if(s < 0)   s += mod;
            long m = 1;
            for(int i = 1; i < k+3; i++) {
                m = m * (n-i) % mod;
            }
            out.println(s * m % mod);
        }
    }

    long mp(long b, long e) {
        long r = 1;
        while(e > 0) {
            if((e&1) == 1)  r = (r * b) % mod;
            b = (b * b) % mod;
            e >>= 1;
        }
        return r;
    }

    //---------- I/O Template ----------

    public static void main(String[] args) { new utkarsh().run(); }
    void run() {
        is = System.in;
        out = new PrintWriter(System.out);
        long start = System.currentTimeMillis();
        solve();
        long end = System.currentTimeMillis();
        if(SHOW_TIME) out.println("\n" + (end - start) + " ms");
        out.flush();
    }

    byte input[] = new byte[1024];
    int len = 0, ptr = 0;

    int readByte() {
        if(ptr >= len) { ptr = 0;
            try { len = is.read(input); }
            catch(IOException e) { throw new InputMismatchException(); }
            if(len <= 0) { return -1; }
        } return input[ptr++];
    }
    boolean isSpaceChar(int c) { return !( c >= 33 && c <= 126 ); }
    int skip() {
        int b = readByte();
        while(b != -1 && isSpaceChar(b)) { b = readByte(); }
        return b;
    }

    char nc() { return (char)skip(); }
    String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while(!isSpaceChar(b)) { sb.appendCodePoint(b); b = readByte(); }
        return sb.toString();
    }
    String nLine() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while( !(isSpaceChar(b) && b != ' ') ) { sb.appendCodePoint(b); b = readByte(); }
        return sb.toString();
    }
    int ni() {
        int n = 0, b = readByte();
        boolean minus = false;
        while(b != -1 && !( (b >= '0' && b <= '9') || b == '-')) { b = readByte(); }
        if(b == '-') { minus = true; b = readByte(); }
        if(b == -1) { return -1; }  //no input
        while(b >= '0' && b <= '9') { n = n * 10 + (b - '0'); b = readByte(); }
        return minus ? -n : n;
    }
    long nl() {
        long n = 0L;    int b = readByte();
        boolean minus = false;
        while(b != -1 && !( (b >= '0' && b <= '9') || b == '-')) { b = readByte(); }
        if(b == '-') { minus = true; b = readByte(); }
        while(b >= '0' && b <= '9') { n = n * 10 + (b - '0'); b = readByte(); }
        return minus ? -n : n;
    }

    double nd() { return Double.parseDouble(ns()); }
    float nf() { return Float.parseFloat(ns()); }
    int[] na(int n) {
        int a[] = new int[n];
        for(int i = 0; i < n; i++) { a[i] = ni(); }
        return a;
    }
    char[] ns(int n) {
        char c[] = new char[n];
        int i, b = skip();
        for(i = 0; i < n; i++) {
            if(isSpaceChar(b)) { break; }
            c[i] = (char)b; b = readByte();
        } return i == n ? c : Arrays.copyOf(c,i);
    }
}

//package que_a;

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

public class utkarsh {

    InputStream is;
    PrintWriter out;

    long mod = (long) (1e9 + 7), inf = (long) (8e18);
    boolean SHOW_TIME, debug;

    long fact[], inv[];

    void getF(int n) {
        fact = new long[n];
        inv = new long[n];
        fact[0] = fact[1] = 1;
        inv[0] = inv[1] = 1;
        for(int i = 2; i < n; i++) {
            fact[i] = (fact[i-1] * i) % mod;
            inv[i] = mp(fact[i], mod - 2);
        }
    }

    void solve() {
        //Enter code here utkarsh
        //SHOW_TIME = true;
	//debug = true;
        int n = ni(), k = ni();
        long ans[] = new long[k + 123];
        for(int i = 1; i < k+123; i++) {
            ans[i] = ans[i-1] + mp(i, k);
            if(ans[i] >= mod)   ans[i] -= mod;
        }
        if(n < k+123)   out.println(ans[n] % mod);
        else {
            getF(k+123);

            long s = 0;
            int p = 1;
            for(int i = k+122; i >= 1; i--) {
                s += mp(n-i, mod-2) * inv[i-1] % mod * inv[k+122-i] % mod * ans[i] * p;
                if(s >= inf)    s -= inf;
                if(s <= -inf)    s += inf;
                p = -p;
            }
            s %= mod;
            if(s < 0)   s += mod;
            long m = 1;
            for(int i = 1; i < k+123; i++) {
                m = m * (n-i) % mod;
            }
            out.println(s * m % mod);
        }
    }

    long mp(long b, long e) {
        long r = 1;
        while(e > 0) {
            if((e&1) == 1)  r = (r * b) % mod;
            b = (b * b) % mod;
            e >>= 1;
        }
        return r;
    }

    //---------- I/O Template ----------

    public static void main(String[] args) { new utkarsh().run(); }
    void run() {
        is = System.in;
        out = new PrintWriter(System.out);
        long start = System.currentTimeMillis();
        solve();
        long end = System.currentTimeMillis();
        if(SHOW_TIME) out.println("\n" + (end - start) + " ms");
        out.flush();
    }

    byte input[] = new byte[1024];
    int len = 0, ptr = 0;

    int readByte() {
        if(ptr >= len) { ptr = 0;
            try { len = is.read(input); }
            catch(IOException e) { throw new InputMismatchException(); }
            if(len <= 0) { return -1; }
        } return input[ptr++];
    }
    boolean isSpaceChar(int c) { return !( c >= 33 && c <= 126 ); }
    int skip() {
        int b = readByte();
        while(b != -1 && isSpaceChar(b)) { b = readByte(); }
        return b;
    }

    char nc() { return (char)skip(); }
    String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while(!isSpaceChar(b)) { sb.appendCodePoint(b); b = readByte(); }
        return sb.toString();
    }
    String nLine() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while( !(isSpaceChar(b) && b != ' ') ) { sb.appendCodePoint(b); b = readByte(); }
        return sb.toString();
    }
    int ni() {
        int n = 0, b = readByte();
        boolean minus = false;
        while(b != -1 && !( (b >= '0' && b <= '9') || b == '-')) { b = readByte(); }
        if(b == '-') { minus = true; b = readByte(); }
        if(b == -1) { return -1; }  //no input
        while(b >= '0' && b <= '9') { n = n * 10 + (b - '0'); b = readByte(); }
        return minus ? -n : n;
    }
    long nl() {
        long n = 0L;    int b = readByte();
        boolean minus = false;
        while(b != -1 && !( (b >= '0' && b <= '9') || b == '-')) { b = readByte(); }
        if(b == '-') { minus = true; b = readByte(); }
        while(b >= '0' && b <= '9') { n = n * 10 + (b - '0'); b = readByte(); }
        return minus ? -n : n;
    }

    double nd() { return Double.parseDouble(ns()); }
    float nf() { return Float.parseFloat(ns()); }
    int[] na(int n) {
        int a[] = new int[n];
        for(int i = 0; i < n; i++) { a[i] = ni(); }
        return a;
    }
    char[] ns(int n) {
        char c[] = new char[n];
        int i, b = skip();
        for(i = 0; i < n; i++) {
            if(isSpaceChar(b)) { break; }
            c[i] = (char)b; b = readByte();
        } return i == n ? c : Arrays.copyOf(c,i);
    }
}