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


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

/**
 * @author Don Li
 */
public class TheOverdosingUbiquity {

    int N = 300;
    int MOD = (int) 1e9 + 7;

    Map<Integer, Integer> map = new HashMap<>();

    int[] num = new int[N];
    List<Integer>[] G = new List[N];

    int tot = 0;
    boolean[] vis = new boolean[N];

    void solve() {
        int n = in.nextInt(), m = in.nextInt();
        int[] fr = new int[m], to = new int[m];
        for (int i = 0; i < m; i++) {
            fr[i] = in.nextInt();
            to[i] = in.nextInt();
        }

        int d = 0;
        while ((1 << d) <= n) d++;

        getId(1);
        for (int i = 0; i < m; i++) {
            int u = fr[i];
            while (u > 0) {
                getId(u);
                u >>= 1;
            }
            u = to[i];
            while (u > 0) {
                getId(u);
                u >>= 1;
            }
        }

        for (int i = 0; i < N; i++) G[i] = new ArrayList<>();
        for (int u : map.keySet()) {
            int id = map.get(u);
            if (u > 1) {
                addEdge(getId(u), getId(u >> 1));
            }
            num[id] = calcSize(u, n, d);
        }

        dfs(0, -1);

        for (int i = 0; i < m; i++) {
            addEdge(getId(fr[i]), getId(to[i]));
        }

        int res = 0;
        for (int i = 0; i < map.size(); i++) {
            tot = 0;
            dfs(i);
            res = (int) ((res + (long) tot * num[i] % MOD) % MOD);
        }
        out.println(res);
    }

    int getId(int x) {
        if (!map.containsKey(x)) map.put(x, map.size());
        return map.get(x);
    }

    void addEdge(int u, int v) {
        G[u].add(v);
        G[v].add(u);
    }

    int calcSize(int u, int n, int d) {
        int t = u, c = 0;
        while (t > 0) {
            c++;
            t >>= 1;
        }
        int sz = (1 << (d - c + 1)) - 1;
        t = c;
        while (t < d) {
            t++;
            u = u << 1 | 1;
        }
        return sz - Math.max(0, Math.min(u - n, 1 << (d - c)));
    }

    void dfs(int u, int p) {
        for (int v : G[u]) {
            if (v != p) {
                num[u] -= num[v];
                dfs(v, u);
            }
        }
    }

    void dfs(int u) {
        tot = (tot + num[u]) % MOD;
        vis[u] = true;
        for (int v : G[u]) {
            if (!vis[v]) dfs(v);
        }
        vis[u] = false;
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new TheOverdosingUbiquity().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

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

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

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

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

public class MainD {
	static final StdIn in = new StdIn();
	static final PrintWriter out = new PrintWriter(System.out);
	static final long M=(long)1e9+7;
	static int n=in.nextInt(), m=in.nextInt();
	static Map<Integer, Node> graph = new HashMap<Integer, Node>();

	public static void main(String[] args) {
		addNode(1);
		for(int i=0; i<m; ++i) {
			int u=in.nextInt(), v=in.nextInt();
			addNode(u).adj.add(v);
			addNode(v).adj.add(u);
		}
		for(Map.Entry<Integer, Node> nodeEntry : graph.entrySet()) {
			Node u=nodeEntry.getValue();
			for(int i=u.adj.size()-1; i>=0; --i) {
				if(!graph.containsKey(u.adj.get(i))) {
					u.s+=sts(u.adj.get(i));
					u.adj.remove(i);
				}
			}
		}
		long ans=0;
		for(Map.Entry<Integer, Node> nodeEntry : graph.entrySet())
			ans=(dfs(nodeEntry.getKey(), 0)+ans)%M;
		out.println(ans);
		out.close();
	}

	static Node addNode(int u) {
		if(u<=0)
			return null;
		Node node = graph.get(u);
		if(node!=null)
			return node;
		node = new Node();
		if(u>1)
			node.adj.add(u/2);
		if(u*2<=n)
			node.adj.add(u*2);
		if(u*2+1<=n)
			node.adj.add(u*2+1);
		graph.put(u, node);
		addNode(u/2);
		return node;
	}

	static long sts(int u) {
		long res=0;
		int l=u, r=u;
		while(r<=n) {
			res+=r-l+1;
			l=2*l;
			r=2*r+1;
		}
		return (res+Math.min(r, n)-Math.min(l, n+1)+1)%M;
	}

	static long dfs(int u, long ps) {
		Node node=graph.get(u);
		if(ps==0)
			ps=node.s;
		node.active=true;
		long res=ps*node.s;
		for(int v : node.adj)
			if(!graph.get(v).active)
				res+=dfs(v, ps);
		node.active=false;
		return res;
	}

	static class Node {
		List<Integer> adj = new ArrayList<Integer>();
		long s=1;
		boolean active;
	}

	interface Input {
		public String next();
		public String nextLine();
		public int nextInt();
		public long nextLong();
		public double nextDouble();
	}
	static class StdIn implements Input {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;
		public StdIn() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public StdIn(InputStream in) {
			try{
				din = new DataInputStream(in);
			} catch(Exception e) {
				throw new RuntimeException();
			}
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public String next() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == ' ' || c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c=read();
			}
			return s.toString();
		}
		public String nextLine() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c = read();
			}
			return s.toString();
		}
		public int nextInt() {
			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 int[] readIntArray(int n) {
			int[] ar = new int[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextInt();
			return ar;
		}
		public long nextLong() {
			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 long[] readLongArray(int n) {
			long[] ar = new long[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextLong();
			return ar;
		}
		public double nextDouble() {
			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() {
			try{
				if (bufferPointer == bytesRead)
					fillBuffer();
				return buffer[bufferPointer++];
			} catch(IOException e) {
				throw new RuntimeException();
			}
		}
		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}
}

//package round439;
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 = "3 1 2 3";
//	String INPUT = "2 1 1 2";
//	String INPUT = "4 1 2 3";
//	String INPUT = "5 1 4 5";
//	String INPUT = "5 1 3 5";
//	String INPUT = "4 1 1 3";
//	String INPUT = "4 2\r\n" +
//			"2 3 1 2 ";
//	String INPUT = "4 2\r\n" +
//			"2 4 1 4 ";
	String INPUT = "";

	//    A1 A2 A3 ...
	// A0              An
	// A0*(A1+...+An)
	// A1*(A2+...+An)
	// ((A0+..+An)^2-A0^2-..-An^2)/2

	void solve()
	{
		int n = ni(), m = ni();
		int[][] ps = new int[m][];
		for(int i = 0;i < m;i++){
			ps[i] = na(2);
		}
//		for(int i = 1;i <= n;i++)tr(i, n, count(i,n));
		int mod = 1000000007;
		long ans = (long)n*n % mod;
		for(int i = 1;i < 1<<m;i++){
			int[] inds = new int[Integer.bitCount(i)];
			int p = 0;
			for(int j = 0;j < m;j++){
				if(i<<~j<0)inds[p++] = j;
			}
			int o = Integer.bitCount(i);
			do{
				// 0:0->1, 1:1->0
				for(int ptn = 0;ptn < 1<<o;ptn++){
					ans += go(inds, ptn, ps, n);
					ans %= mod;
//					tr("ans", i, inds, ptn, ans);
				}
			}while(nextPermutation(inds));
		}
		out.println(ans % mod);
	}

	long go(int[] inds, int ptn, int[][] ps, int n)
	{
		// collide?
		int[][] paths = new int[2*(inds.length-1)][];
		int p = 0;
		for(int i = 0;i < inds.length-1;i++){
			int f = ptn<<~i>=0 ? ps[inds[i]][1] : ps[inds[i]][0];
			int t = ptn<<~(i+1)>=0 ? ps[inds[i+1]][0] : ps[inds[i+1]][1];
			int lca = lca(f, t);
			paths[p++] = new int[]{f, lca};
			if(lca != t){
				int clca = t/(Integer.highestOneBit(t)/Integer.highestOneBit(lca)/2);
				paths[p++] = new int[]{t, clca};
			}
		}
		for(int i = 0;i < p;i++){
			for(int j = i+1;j < p;j++){
				if(col(paths[i], paths[j]))return 0;
			}
		}
//		tr("UM");
		int[] st = {
				ptn<<~0>=0 ? ps[inds[0]][0] : ps[inds[0]][1],
				ptn<<~(inds.length-1)>=0 ? ps[inds[inds.length-1]][1] : ps[inds[inds.length-1]][0]
		};
		if(st[0] == st[1])return 0;
//		tr("OK", st);
		int[] tops = new int[2];
		for(int j = 0;j < 2;j++){
			int top = 0;
			for(int i = 0;i < p;i++){
				int lcad = lca(st[j], paths[i][0]);
				if(Integer.highestOneBit(lcad) >= Integer.highestOneBit(paths[i][1])){
					top = Math.max(top, lcad);
				}
			}
			if(top == st[j])return 0; // collide

			if(top == 0){
				top = 1;
			}else{
				int otop = top;
				top = st[j] / (Integer.highestOneBit(st[j]) / Integer.highestOneBit(top) / 2);
				assert top / 2 == otop;
			}
			tops[j] = top;
		}
//		tr(st, tops);
		if(tops[0] == tops[1]){
			return calc(tops[0], paths, p, n, st[0], st[1]);
		}else{
			return (long)all(tops[0], paths, p, n, st[0]) *
					all(tops[1], paths, p, n, st[1]);
		}
	}

	int count(int x, int n)
	{
		int first = Integer.highestOneBit(n) / Integer.highestOneBit(x) * x;
		int last = Integer.highestOneBit(n) / Integer.highestOneBit(x) * (x+1);
		int base = Integer.highestOneBit(n) / Integer.highestOneBit(x) - 1;
		return base + Math.max(0, Math.min(last-first, n-first+1));
	}

	int all(int top, int[][] paths, int p, int n, int tar)
	{
		int[] lroot = new int[p];
		int q = 0;
		for(int i = 0;i < p;i++){
			int llca = lca(paths[i][1], tar);
			if(Integer.highestOneBit(llca) < Integer.highestOneBit(top))continue;
			lroot[q++] = paths[i][1];
		}
		boolean[] ng = new boolean[q];
		for(int i = 0;i < q;i++){
			for(int k = 0;k < q;k++){
				if(i == k)continue;
				if(lca(lroot[i], lroot[k]) == lroot[k]){
					ng[i] = true;
				}
			}
		}
		int all = count(top, n);
		for(int i = 0;i < q;i++){
			if(!ng[i]){
				all -= count(lroot[i], n);
			}
		}
		return all;
	}

	long calc(int top, int[][] paths, int p, int n, int t1, int t2)
	{
		int[] lroot = new int[p];
		int q = 0;
		for(int i = 0;i < p;i++){
			int llca = lca(paths[i][1], t1);
			if(Integer.highestOneBit(llca) < Integer.highestOneBit(top))continue;
			lroot[q++] = paths[i][1];
		}
		boolean[] ng = new boolean[q];
		for(int i = 0;i < q;i++){
			for(int k = 0;k < q;k++){
				if(i == k)continue;
				if(lca(lroot[i], lroot[k]) == lroot[k]){
					ng[i] = true;
				}
			}
		}
		int[] route = new int[100];
		int tl = lca(t1, t2);
		int r = 0;
		for(int z = t1;z != tl;z /= 2){
			route[r++] = z;
		}
		int or = r;
		for(int z = t2;z != tl;z /= 2){
			route[r++] = z;
		}
		route[r++] = tl;
		for(int i = or, j = r-1;i < j;i++,j--){
			int d = route[i]; route[i] = route[j]; route[j] = d;
		}
		route = Arrays.copyOf(route, r);
		int[] has = new int[r];
		for(int i = 0;i < r;i++){
			has[i] = count(route[i], n);
		}
		for(int i = or-1;i >= 1;i--){
			has[i] -= has[i-1];
		}
		for(int i = or+1;i < r-1;i++){
			has[i] -= has[i+1];
		}
		for(int i = 0;i < q;i++){
			if(!ng[i] && lca(lroot[i], tl) == tl){
				int hit = lca(lroot[i], t1);
				if(hit == tl)hit = lca(lroot[i], t2);
				for(int j = 0;j < r;j++){
					if(route[j] == hit){
						has[j] -= count(lroot[i], n);
						break;
					}
				}
			}
		}
		if(tl != t1 && tl != t2){
			has[or] = count(top, n) - count(tl, n) + 1;

			for(int i = 0;i < q;i++){
				if(!ng[i] && lca(lroot[i], tl) != tl){
					has[or] -= count(lroot[i], n);
				}
			}
		}else{
			int tlch = route[or == 0 ? 1 : r - 2];
			has[or] = count(top, n) - count(tlch, n);
			for(int i = 0;i < q;i++){
				if(!ng[i] && lca(lroot[i], tlch) != tlch){
					has[or] -= count(lroot[i], n);
				}
			}
		}
//		tr("route", route);
//		tr("has", has, lroot);
		long s1 = 0;
		long s2 = 0;
		for(int v : has){
			s1 += v;
			s2 += (long)v*v;
		}
		return (s1*s1-s2)/2;
	}

	public static int lca(long x, long y)
	{
		long xx = x<<Long.numberOfLeadingZeros(x);
		long yy = y<<Long.numberOfLeadingZeros(y);
		return (int)(x>>>Math.max(Long.numberOfLeadingZeros(Math.min(x, y)), 64-Long.numberOfLeadingZeros(xx^yy))-Long.numberOfLeadingZeros(x));
	}

	boolean col(int[] a, int[] b)
	{
		int l = lca(a[0], b[0]);
		if(Integer.highestOneBit(a[1]) <= Integer.highestOneBit(l) && Integer.highestOneBit(b[1]) <= Integer.highestOneBit(l)){
			return true;
		}else{
			return false;
		}
	}

	static boolean nextPermutation(int[] src) {
		int i;
		for (i = src.length - 2; i >= 0 && src[i] > src[i + 1]; i--)
			;
		if (i == -1)
			return false;
		int j;
		for (j = i + 1; j < src.length && src[i] < src[j]; j++)
			;
		int d = src[i];
		src[i] = src[j - 1];
		src[j - 1] = d;
		for (int p = i + 1, q = src.length - 1; p < q; p++, q--) {
			d = src[p];
			src[p] = src[q];
			src[q] = d;
		}
		return true;
	}

	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.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Iterator;
import java.io.BufferedWriter;
import java.util.Collection;
import java.util.Random;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

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

  static class TaskD {
    static final IntModular MOD = new IntModular();
    int n;
    int m;
    int[] end1;
    int[] end2;
    int res;
    boolean[] visited;
    BidirectionalGraph graph;
    IntArrayList points;
    IntArrayList pointCounts;

    public void solve(int testNumber, QuickScanner in, QuickWriter out) {
      n = in.nextInt();
      m = in.nextInt();
      end1 = new int[m];
      end2 = new int[m];
      in.nextInts(m, end1, end2);
      initPoints();
      initGraph();
      res = 0;
      visited = new boolean[points.size];
      for (int i = 0; i < points.size; ++i) {
        res = MOD.add(res, MOD.mul(pointCounts.get(i), dfs(i)));
      }
      out.println(res);
    }

    int dfs(int u) {
      visited[u] = true;
      int res = pointCounts.get(u);
      for (int v : graph.outNodes(u))
        if (!visited[v]) {
          res = MOD.add(res, dfs(v));
        }
      visited[u] = false;
      return res;
    }

    void initGraph() {
      graph = new BidirectionalGraph(points.size, points.size + m);
      points.forEach((point) -> {
        if (point > 1) {
          graph.add(points.lowerBound(point), points.lowerBound(point >> 1));
        }
      });
      for (int i = 0; i < m; ++i) {
        graph.add(points.lowerBound(end1[i]), points.lowerBound(end2[i]));
      }
    }

    void initPoints() {
      points = new IntArrayList();
      for (int i = 0; i < m; ++i) {
        addKeyPoints(end1[i]);
        addKeyPoints(end2[i]);
      }
      points.sortAndUnique();
      if (points.isEmpty()) {
        points.add(1);
      }
      pointCounts = new IntArrayList(points.size);
      for (int point : points) {
        int cnt = 1;
        if (!points.binarySearch(point << 1)) {
          cnt += calcSubtree(point << 1);
        }
        if (!points.binarySearch((point << 1) | 1)) {
          cnt += calcSubtree((point << 1) | 1);
        }
        pointCounts.add(cnt);
      }
    }

    int calcSubtree(int x) {
      int lower = x, upper = x;
      int res = 0;
      for (; lower <= n; lower <<= 1, upper = (upper << 1) | 1) {
        res += Math.min(n, upper) - lower + 1;
        if (n <= upper) break;
      }
      return res;
    }

    void addKeyPoints(int x) {
      for (; x > 0; x >>= 1) points.add(x);
    }

  }

  static abstract class AbstractBidirectionalGraph extends AbstractDirectedGraph implements BidirectionalGraphInterface {
    public AbstractBidirectionalGraph() {
      super();
    }

    public AbstractBidirectionalGraph(int vertexCapacity, int edgeCapacity) {
      super(vertexCapacity, edgeCapacity << 1);
    }

    public AbstractBidirectionalGraph(int vertexCapacity, int edgeCapacity, boolean initialize) {
      super(vertexCapacity, edgeCapacity << 1, initialize);
    }

    public void add(int u, int v) {
      super.add(u, v);
      super.add(v, u);
    }

  }

  static class QuickWriter {
    private final PrintWriter writer;

    public QuickWriter(OutputStream outputStream) {
      this.writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

    public QuickWriter(Writer writer) {
      this.writer = new PrintWriter(writer);
    }

    public void print(Object... objects) {
      for (int i = 0; i < objects.length; ++i) {
        if (i > 0) {
          writer.print(' ');
        }
        writer.print(objects[i]);
      }
    }

    public void println(Object... objects) {
      print(objects);
      writer.println();
    }

    public void close() {
      writer.close();
    }

  }

  static final class BidirectionalGraph extends AbstractBidirectionalGraph {
    public BidirectionalGraph() {
      super();
    }

    public BidirectionalGraph(int vertexCapacity, int edgeCapacity) {
      super(vertexCapacity, edgeCapacity);
    }

    public void createVertexStorage(int vertexCapacity) {
    }

    public void expandEdgeStorage(int edgeCapacity) {
    }

    public void initVertexStorage(int vertexCnt) {
    }

  }

  static class QuickScanner {
    private static final int BUFFER_SIZE = 1024;
    private InputStream stream;
    private byte[] buffer;
    private int currentPosition;
    private int numberOfChars;

    public QuickScanner(InputStream stream) {
      this.stream = stream;
      this.buffer = new byte[BUFFER_SIZE];
      this.currentPosition = 0;
      this.numberOfChars = 0;
    }

    public int nextInt() {
      int c = nextNonSpaceChar();
      boolean positive = true;
      if (c == '-') {
        positive = false;
        c = nextChar();
      }
      int res = 0;
      do {
        if (c < '0' || '9' < c) throw new RuntimeException();
        res = res * 10 + (c - '0');
        c = nextChar();
      } while (!isSpaceChar(c));
      return positive ? res : -res;
    }

    public void nextInts(int n, int[]... res) {
      int m = res.length;
      for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j) {
          res[j][i] = nextInt();
        }
    }

    public int nextNonSpaceChar() {
      int res = nextChar();
      for (; isSpaceChar(res) || res < 0; res = nextChar()) ;
      return res;
    }

    public int nextChar() {
      if (numberOfChars == -1) {
        throw new RuntimeException();
      }
      if (currentPosition >= numberOfChars) {
        currentPosition = 0;
        try {
          numberOfChars = stream.read(buffer);
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
        if (numberOfChars <= 0) {
          return -1;
        }
      }
      return buffer[currentPosition++];
    }

    public boolean isSpaceChar(int c) {
      return c == ' ' || c == '\t' || isEndOfLineChar(c);
    }

    public boolean isEndOfLineChar(int c) {
      return c == '\n' || c == '\r' || c < 0;
    }

  }

  static interface IntCollection {
    int size();

    default boolean isEmpty() {
      return size() == 0;
    }

  }

  static class IntArrayList implements Displayable, IntCollection, Iterable<Integer> {
    private static final int[] EMPTY = {};
    public int[] values;
    public int size;

    public IntArrayList() {
      values = EMPTY;
      clear();
    }

    public IntArrayList(int capacity) {
      values = new int[IntUtils.nextPow2(capacity)];
      clear();
    }

    public IntArrayList(Collection<Integer> collection) {
      this(collection.size());
      addAll(collection);
    }

    public void clear() {
      size = 0;
    }

    public int size() {
      return size;
    }

    public void add(int value) {
      ensureCapacity(size + 1);
      addInternal(value);
    }

    public void addAll(Collection<Integer> values) {
      ensureCapacity(size + values.size());
      for (int value : values) {
        addInternal(value);
      }
    }

    public int get(int idx) {
      if (idx >= size) throw new ArrayIndexOutOfBoundsException();
      return values[idx];
    }

    public void sort() {
      IntArrayUtils.sort(values, 0, size);
    }

    public void unique() {
      size = IntArrayUtils.unique(values, 0, size);
    }

    public void sortAndUnique() {
      sort();
      unique();
    }

    public int lowerBound(int value) {
      return IntArrayUtils.lowerBound(values, 0, size, value);
    }

    public boolean binarySearch(int value) {
      int idx = lowerBound(value);
      return idx < size && get(idx) == value;
    }

    public void ensureCapacity(int capacity) {
      if (capacity <= values.length) return;
      int[] newValues = new int[IntUtils.nextPow2(capacity)];
      for (int i = 0; i < size; ++i) {
        newValues[i] = values[i];
      }
      values = newValues;
    }

    public Iterator<Integer> iterator() {
      return new Iterator<Integer>() {
        private int i = 0;

        public boolean hasNext() {
          return i < size;
        }

        public Integer next() {
          return values[i++];
        }
      };
    }

    private void addInternal(int value) {
      values[size++] = value;
    }

  }

  static class IntArrayUtils {
    private static final Random RANDOM = new Random(1000000007);

    public static int unique(int[] values, int fromIdx, int toIdx) {
      if (fromIdx == toIdx) return 0;
      int res = 1;
      for (int i = fromIdx + 1; i < toIdx; ++i) {
        if (values[i - 1] != values[i]) {
          values[fromIdx + res++] = values[i];
        }
      }
      return res;
    }

    public static void sort(int[] values, int fromIdx, int toIdx) {
      shuffle(values, fromIdx, toIdx);
      Arrays.sort(values, fromIdx, toIdx);
    }

    public static int lowerBound(int[] values, int fromIdx, int toIdx, int value) {
      int res = toIdx;
      for (int lower = fromIdx, upper = toIdx - 1; lower <= upper; ) {
        int medium = (lower + upper) >> 1;
        if (value <= values[medium]) {
          res = medium;
          upper = medium - 1;
        } else {
          lower = medium + 1;
        }
      }
      return res;
    }

    public static void swap(int[] values, int uIdx, int vIdx) {
      if (uIdx == vIdx) return;
      values[uIdx] ^= values[vIdx];
      values[vIdx] ^= values[uIdx];
      values[uIdx] ^= values[vIdx];
    }

    public static void shuffle(int[] values, int fromIdx, int toIdx) {
      for (int i = toIdx - fromIdx - 1; i > 0; --i) {
        swap(values, i + fromIdx, RANDOM.nextInt(i + 1) + fromIdx);
      }
    }

    public static int[] expand(int[] values, int newLength) {
      if (values != null && values.length >= newLength) return values;
      int[] res = new int[newLength];
      if (values == null) return res;
      for (int i = 0; i < values.length; ++i) res[i] = values[i];
      return res;
    }

  }

  static class IntUtils {
    public static boolean isPow2(int n) {
      return n > 0 && (n & (n - 1)) == 0;
    }

    public static int nextPow2(int n) {
      if (n < 1) return 1;
      return isPow2(n) ? n : Integer.highestOneBit(n) << 1;
    }

  }

  static interface DirectedGraphInterface {
  }

  static interface Displayable {
  }

  static abstract class AbstractDirectedGraph implements DirectedGraphInterface {
    protected int vertexCnt;
    protected int currentEdgeCnt;
    protected int[] fromIdx;
    protected int[] toIdx;
    protected int[] nextIn;
    protected int[] nextOut;
    protected int[] lastIn;
    protected int[] lastOut;
    protected int[] inDegree;
    protected int[] outDegree;

    public abstract void createVertexStorage(int vertexCapacity);

    public abstract void expandEdgeStorage(int edgeCapacity);

    public abstract void initVertexStorage(int vertexCnt);

    public AbstractDirectedGraph() {
    }

    public AbstractDirectedGraph(int vertexCapacity, int edgeCapacity) {
      this(vertexCapacity, edgeCapacity, true);
    }

    public AbstractDirectedGraph(int vertexCapacity, int edgeCapacity, boolean initialize) {
      ensureVertexCapacity(vertexCapacity);
      ensureEdgeCapacity(edgeCapacity);
      if (initialize) init(vertexCapacity);
    }

    public void init(int vertexCnt) {
      ensureVertexCapacity(vertexCnt);
      this.vertexCnt = vertexCnt;
      currentEdgeCnt = 0;
      Arrays.fill(inDegree, 0, vertexCnt, 0);
      Arrays.fill(outDegree, 0, vertexCnt, 0);
      Arrays.fill(lastIn, 0, vertexCnt, -1);
      Arrays.fill(lastOut, 0, vertexCnt, -1);
      initVertexStorage(vertexCnt);
    }

    public void add(int fromIdx, int toIdx) {
      ensureEdgeCapacity(currentEdgeCnt + 1);
      this.fromIdx[currentEdgeCnt] = fromIdx;
      this.toIdx[currentEdgeCnt] = toIdx;
      ++outDegree[fromIdx];
      ++inDegree[toIdx];
      nextOut[currentEdgeCnt] = lastOut[fromIdx];
      lastOut[fromIdx] = currentEdgeCnt;
      nextIn[currentEdgeCnt] = lastIn[toIdx];
      lastIn[toIdx] = currentEdgeCnt;
      ++currentEdgeCnt;
    }

    public int nextOut(int edgeIdx) {
      return nextOut[edgeIdx];
    }

    public Iterable<Integer> outNodes(int nodeIdx) {
      return () -> new Iterator<Integer>() {
        private int edgeIdx = lastOut[nodeIdx];

        public boolean hasNext() {
          return edgeIdx >= 0;
        }

        public Integer next() {
          int res = toIdx[edgeIdx];
          edgeIdx = nextOut(edgeIdx);
          return res;
        }
      };
    }

    private void ensureVertexCapacity(int vertexCapacity) {
      if (lastIn != null && lastIn.length >= vertexCapacity) return;
      int capacity = IntUtils.nextPow2(vertexCapacity);
      lastIn = new int[capacity];
      lastOut = new int[capacity];
      inDegree = new int[capacity];
      outDegree = new int[capacity];
      createVertexStorage(capacity);
    }

    private void ensureEdgeCapacity(int edgeCapacity) {
      if (fromIdx != null && fromIdx.length >= edgeCapacity) return;
      int capacity = IntUtils.nextPow2(edgeCapacity);
      fromIdx = IntArrayUtils.expand(fromIdx, capacity);
      toIdx = IntArrayUtils.expand(toIdx, capacity);
      nextIn = IntArrayUtils.expand(nextIn, capacity);
      nextOut = IntArrayUtils.expand(nextOut, capacity);
      expandEdgeStorage(capacity);
    }

  }

  static interface BidirectionalGraphInterface extends DirectedGraphInterface {
  }

  static class IntModular {
    private static final int MOD = 1000000007;
    public final int mod;
    private final int[] x;

    public IntModular() {
      this(MOD);
    }

    public IntModular(int mod) {
      this.mod = mod;
      this.x = new int[2];
    }

    public int add(int a, int b) {
      return fix(a + b);
    }

    public int fix(int a) {
      a = slightFix(a);
      return 0 <= a && a < mod ? a : slightFix(a % mod);
    }

    public int mul(int a, int b) {
      return a > 0
          ? (b < mod / a ? a * b : (int) ((long) a * b % mod))
          : 0;
    }

    private int slightFix(int a) {
      return a >= mod
          ? a - mod
          : a < 0 ? a + mod : a;
    }

  }
}

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

public class MainD {
	static final StdIn in = new StdIn();
	static final PrintWriter out = new PrintWriter(System.out);
	static final long M=(long)1e9+7;
	static int n=in.nextInt(), m=in.nextInt();
	static Map<Integer, Node> graph = new HashMap<Integer, Node>();

	public static void main(String[] args) {
		addNode(1);
		for(int i=0; i<m; ++i) {
			int u=in.nextInt(), v=in.nextInt();
			addNode(u).adj.add(v);
			addNode(v).adj.add(u);
		}
		for(Map.Entry<Integer, Node> nodeEntry : graph.entrySet()) {
			Node u=nodeEntry.getValue();
			for(int i=u.adj.size()-1; i>=0; --i) {
				if(!graph.containsKey(u.adj.get(i))) {
					u.s+=sts(u.adj.get(i));
					u.adj.remove(i);
				}
			}
		}
		long ans=0;
		for(Map.Entry<Integer, Node> nodeEntry : graph.entrySet())
			ans=(dfs(nodeEntry.getKey(), 0)+ans)%M;
		out.println(ans);
		out.close();
	}

	static Node addNode(int u) {
		if(u<=0)
			return null;
		Node node = graph.get(u);
		if(node!=null)
			return node;
		node = new Node();
		if(u>1)
			node.adj.add(u/2);
		if(u*2<=n)
			node.adj.add(u*2);
		if(u*2+1<=n)
			node.adj.add(u*2+1);
		graph.put(u, node);
		addNode(u/2);
		return node;
	}

	static long sts(int u) {
		long res=0;
		int l=u, r=u;
		while(r<=n) {
			res+=r-l+1;
			l=2*l;
			r=2*r+1;
		}
		return (res+Math.min(r, n)-Math.min(l, n))%M;
	}

	static long dfs(int u, long ps) {
		Node node=graph.get(u);
		if(ps==0)
			ps=node.s;
		node.active=true;
		long res=ps*node.s;
		for(int v : node.adj)
			if(!graph.get(v).active)
				res+=dfs(v, ps);
		node.active=false;
		return res;
	}

	static class Node {
		List<Integer> adj = new ArrayList<Integer>();
		long s=1;
		boolean active;
	}

	interface Input {
		public String next();
		public String nextLine();
		public int nextInt();
		public long nextLong();
		public double nextDouble();
	}
	static class StdIn implements Input {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;
		public StdIn() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public StdIn(InputStream in) {
			try{
				din = new DataInputStream(in);
			} catch(Exception e) {
				throw new RuntimeException();
			}
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
		public String next() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == ' ' || c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c=read();
			}
			return s.toString();
		}
		public String nextLine() {
			int c;
			while((c=read())!=-1&&(c==' '||c=='\n'||c=='\r'));
			StringBuilder s = new StringBuilder();
			while (c != -1)
			{
				if (c == '\n'||c=='\r')
					break;
				s.append((char)c);
				c = read();
			}
			return s.toString();
		}
		public int nextInt() {
			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 int[] readIntArray(int n) {
			int[] ar = new int[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextInt();
			return ar;
		}
		public long nextLong() {
			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 long[] readLongArray(int n) {
			long[] ar = new long[n];
			for(int i=0; i<n; ++i)
				ar[i]=nextLong();
			return ar;
		}
		public double nextDouble() {
			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() {
			try{
				if (bufferPointer == bytesRead)
					fillBuffer();
				return buffer[bufferPointer++];
			} catch(IOException e) {
				throw new RuntimeException();
			}
		}
		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}
}

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

/**
 * @author Don Li
 */
public class TheOverdosingUbiquity {

    int N = 200;
    int MOD = (int) 1e9 + 7;

    Map<Integer, Integer> map = new HashMap<>();

    int[] num = new int[N];
    List<Integer>[] G = new List[N];

    int tot = 0;
    boolean[] vis = new boolean[N];

    void solve() {
        int n = in.nextInt(), m = in.nextInt();
        int[] fr = new int[m], to = new int[m];
        for (int i = 0; i < m; i++) {
            fr[i] = in.nextInt();
            to[i] = in.nextInt();
        }

        int d = 0;
        while ((1 << d) <= n) d++;

        getId(1);
        for (int i = 0; i < m; i++) {
            int u = fr[i];
            while (u > 0) {
                getId(u);
                u >>= 1;
            }
            u = to[i];
            while (u > 0) {
                getId(u);
                u >>= 1;
            }
        }

        for (int i = 0; i < N; i++) G[i] = new ArrayList<>();
        for (int u : map.keySet()) {
            int id = map.get(u);
            if (u > 1) {
                addEdge(getId(u), getId(u >> 1));
            }
            num[id] = calcSize(u, n, d);
        }

        dfs(0, -1);

        for (int i = 0; i < m; i++) {
            addEdge(getId(fr[i]), getId(to[i]));
        }

        int res = 0;
        for (int i = 0; i < map.size(); i++) {
            tot = 0;
            dfs(i);
            res = (int) ((res + (long) tot * num[i] % MOD) % MOD);
        }
        out.println(res);
    }

    int getId(int x) {
        if (!map.containsKey(x)) map.put(x, map.size());
        return map.get(x);
    }

    void addEdge(int u, int v) {
        G[u].add(v);
        G[v].add(u);
    }

    int calcSize(int u, int n, int d) {
        int t = u, c = 0;
        while (t > 0) {
            c++;
            t >>= 1;
        }
        int sz = (1 << (d - c + 1)) - 1; // there are at most 2^(d-c+1)-1 nodes in subtree[u]
        t = c;
        while (t < d) {
            t++;
            u = u << 1 | 1;
        }
        return sz - Math.max(0, Math.min(u - n, 1 << (d - c))); // there are at most 2^(d-c) leaf nodes
    }

    void dfs(int u, int p) {
        for (int v : G[u]) {
            if (v != p) {
                num[u] -= num[v];
                dfs(v, u);
            }
        }
    }

    void dfs(int u) {
        tot += num[u];
        vis[u] = true;
        for (int v : G[u]) {
            if (!vis[v]) dfs(v);
        }
        vis[u] = false;
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new TheOverdosingUbiquity().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

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

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

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

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Iterator;
import java.io.BufferedWriter;
import java.util.Collection;
import java.util.Random;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

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

  static class TaskD {
    static final IntModular MOD = new IntModular();
    int n;
    int m;
    int[] end1;
    int[] end2;
    IntArrayList points;
    IntArrayList counts;
    IntArrayList covered;
    IntArrayList newCovered;

    public void solve(int testNumber, QuickScanner in, QuickWriter out) {
      n = in.nextInt();
      m = in.nextInt();
      end1 = new int[m];
      end2 = new int[m];
      in.nextInts(m, end1, end2);
      initKeyPoints();
//System.out.printf("points:%s\n", points.toDisplay());
//System.out.printf("points:%s\n", counts.toDisplay());
      int res = MOD.mul(n, n);
      IntArrayList edgeIdxs = new IntArrayList(m);
      for (int mask = (1 << m) - 1; mask > 0; --mask) {
        edgeIdxs.clear();
        for (int i = 0; i < m; ++i)
          if ((mask & (1 << i)) > 0) {
            edgeIdxs.add(i);
          }
        res = MOD.add(res, calcUnordered(edgeIdxs));
      }
      out.println(res);
    }

    void initKeyPoints() {
      points = new IntArrayList();
      for (int i = 0; i < m; ++i) {
        addKeyPoints(end1[i]);
        addKeyPoints(end2[i]);
      }
      points.sortAndUnique();
      counts = new IntArrayList(points.size);
      for (int point : points) {
        int cnt = 1;
        if (!points.binarySearch(point << 1)) {
          cnt += calcSubtree(point << 1);
        }
        if (!points.binarySearch((point << 1) | 1)) {
          cnt += calcSubtree((point << 1) | 1);
        }
        counts.add(cnt);
      }
    }

    int calcSubtree(int x) {
      int lower = x, upper = x;
      int res = 0;
      for (; lower <= n; lower <<= 1, upper = (upper << 1) | 1) {
        res += Math.min(n, upper) - lower + 1;
        if (n <= upper) break;
      }
      return res;
    }

    void addKeyPoints(int x) {
      for (; x > 0; x >>= 1) points.add(x);
    }

    int calcUnordered(IntArrayList edgeIdxs) {
      int res = 0;
      for (int mask = (1 << edgeIdxs.size) - 1; mask >= 0; --mask) {
        res = MOD.add(res, calcOrdered(edgeIdxs, mask));
      }
      return res;
    }

    int calcOrdered(IntArrayList edgeIdxs, int orderMask) {
      if (covered == null) {
        covered = new IntArrayList();
      }
      covered.clear();
      int source = -1, sink = -1;
      for (int i = 0; i < edgeIdxs.size; ++i) {
        int from, to;
        if ((orderMask & (1 << i)) > 0) {
          from = end1[edgeIdxs.get(i)];
          to = end2[edgeIdxs.get(i)];
        } else {
          from = end2[edgeIdxs.get(i)];
          to = end1[edgeIdxs.get(i)];
        }
//System.out.printf("(%d->%d) ", from, to);
        if (source < 0) {
          source = from;
          covered.add(source);
        }
        if (i > 0) addPath(sink, from);
        sink = to;
      }
//System.out.println();
      covered.add(sink);
      int coveredSize = covered.size;
//System.out.printf("\tcovered:%s\n", covered.toDisplay());
      covered.sortAndUnique();
//System.out.printf("\tcovered:%s\n", covered.toDisplay());
//if (coveredSize != covered.size) System.out.printf("\tno %d %d\n", coveredSize, covered.size);
      if (coveredSize != covered.size) return 0;
      int res = 0;
      for (int i = 0; i < points.size; ++i) {
        int u = points.get(i);
        for (int j = 0; j < points.size; ++j) {
          int v = points.get(j);
//if (u != v) System.out.printf("\t(%d,%d)->(%d,%d):%b\n", u, source, v, sink, isValid(u, source, v, sink));
          if (u == v || !isValid(u, source, v, sink)) continue;
          res = MOD.add(res, MOD.mul(counts.get(i), counts.get(j)));
        }
      }
      return res;
    }

    void addPath(int x, int y) {
      while (x != y) {
        if (x < y) {
          covered.add(y);
          y >>= 1;
        } else {
          covered.add(x);
          x >>= 1;
        }
      }
      covered.add(x);
    }

    boolean isValid(int source0, int sink0, int source1, int sink1) {
      if (newCovered == null) {
        newCovered = new IntArrayList();
      }
      newCovered.clear();
//System.out.printf("\t\t(%d,%d)->(%d,%d)\n", source0, sink0, source1, sink1);
//System.out.println("\t\tstep1");
      if (!addPathWithCheck(source0, sink0)) return false;
//System.out.println("\t\tstep2");
      if (!addPathWithCheck(source1, sink1)) return false;
//System.out.printf("\t\tstep3 %s\n", newCovered.toDisplay());
      int size = newCovered.size;
      newCovered.sortAndUnique();
      return size == newCovered.size;
    }

    boolean addPathWithCheck(int x, int y) {
      int sink = y;
      while (x != y) {
        if (x < y) {
          if (sink != y) {
            if (covered.binarySearch(y)) return false;
            newCovered.add(y);
          }
          y >>= 1;
        } else {
          if (covered.binarySearch(x)) return false;
          newCovered.add(x);
          x >>= 1;
        }
      }
      if (sink != x) {
        if (covered.binarySearch(x)) return false;
        newCovered.add(x);
      }
      return true;
    }

  }

  static class QuickWriter {
    private final PrintWriter writer;

    public QuickWriter(OutputStream outputStream) {
      this.writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

    public QuickWriter(Writer writer) {
      this.writer = new PrintWriter(writer);
    }

    public void print(Object... objects) {
      for (int i = 0; i < objects.length; ++i) {
        if (i > 0) {
          writer.print(' ');
        }
        writer.print(objects[i]);
      }
    }

    public void println(Object... objects) {
      print(objects);
      writer.println();
    }

    public void close() {
      writer.close();
    }

  }

  static class QuickScanner {
    private static final int BUFFER_SIZE = 1024;
    private InputStream stream;
    private byte[] buffer;
    private int currentPosition;
    private int numberOfChars;

    public QuickScanner(InputStream stream) {
      this.stream = stream;
      this.buffer = new byte[BUFFER_SIZE];
      this.currentPosition = 0;
      this.numberOfChars = 0;
    }

    public int nextInt() {
      int c = nextNonSpaceChar();
      boolean positive = true;
      if (c == '-') {
        positive = false;
        c = nextChar();
      }
      int res = 0;
      do {
        if (c < '0' || '9' < c) throw new RuntimeException();
        res = res * 10 + (c - '0');
        c = nextChar();
      } while (!isSpaceChar(c));
      return positive ? res : -res;
    }

    public void nextInts(int n, int[]... res) {
      int m = res.length;
      for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j) {
          res[j][i] = nextInt();
        }
    }

    public int nextNonSpaceChar() {
      int res = nextChar();
      for (; isSpaceChar(res) || res < 0; res = nextChar()) ;
      return res;
    }

    public int nextChar() {
      if (numberOfChars == -1) {
        throw new RuntimeException();
      }
      if (currentPosition >= numberOfChars) {
        currentPosition = 0;
        try {
          numberOfChars = stream.read(buffer);
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
        if (numberOfChars <= 0) {
          return -1;
        }
      }
      return buffer[currentPosition++];
    }

    public boolean isSpaceChar(int c) {
      return c == ' ' || c == '\t' || isEndOfLineChar(c);
    }

    public boolean isEndOfLineChar(int c) {
      return c == '\n' || c == '\r' || c < 0;
    }

  }

  static interface IntCollection {
  }

  static class IntArrayList implements Displayable, IntCollection, Iterable<Integer> {
    private static final int[] EMPTY = {};
    public int[] values;
    public int size;

    public IntArrayList() {
      values = EMPTY;
      clear();
    }

    public IntArrayList(int capacity) {
      values = new int[IntUtils.nextPow2(capacity)];
      clear();
    }

    public IntArrayList(Collection<Integer> collection) {
      this(collection.size());
      addAll(collection);
    }

    public void clear() {
      size = 0;
    }

    public void add(int value) {
      ensureCapacity(size + 1);
      addInternal(value);
    }

    public void addAll(Collection<Integer> values) {
      ensureCapacity(size + values.size());
      for (int value : values) {
        addInternal(value);
      }
    }

    public int get(int idx) {
      if (idx >= size) throw new ArrayIndexOutOfBoundsException();
      return values[idx];
    }

    public void sort() {
      IntArrayUtils.sort(values, 0, size);
    }

    public void unique() {
      size = IntArrayUtils.unique(values, 0, size);
    }

    public void sortAndUnique() {
      sort();
      unique();
    }

    public int lowerBound(int value) {
      return IntArrayUtils.lowerBound(values, 0, size, value);
    }

    public boolean binarySearch(int value) {
      int idx = lowerBound(value);
      return idx < size && get(idx) == value;
    }

    public void ensureCapacity(int capacity) {
      if (capacity <= values.length) return;
      int[] newValues = new int[IntUtils.nextPow2(capacity)];
      for (int i = 0; i < size; ++i) {
        newValues[i] = values[i];
      }
      values = newValues;
    }

    public Iterator<Integer> iterator() {
      return new Iterator<Integer>() {
        private int i = 0;

        public boolean hasNext() {
          return i < size;
        }

        public Integer next() {
          return values[i++];
        }
      };
    }

    private void addInternal(int value) {
      values[size++] = value;
    }

  }

  static class IntArrayUtils {
    private static final Random RANDOM = new Random(1000000007);

    public static int unique(int[] values, int fromIdx, int toIdx) {
      if (fromIdx == toIdx) return 0;
      int res = 1;
      for (int i = fromIdx + 1; i < toIdx; ++i) {
        if (values[i - 1] != values[i]) {
          values[fromIdx + res++] = values[i];
        }
      }
      return res;
    }

    public static void sort(int[] values, int fromIdx, int toIdx) {
      shuffle(values, fromIdx, toIdx);
      Arrays.sort(values, fromIdx, toIdx);
    }

    public static int lowerBound(int[] values, int fromIdx, int toIdx, int value) {
      int res = toIdx;
      for (int lower = fromIdx, upper = toIdx - 1; lower <= upper; ) {
        int medium = (lower + upper) >> 1;
        if (value <= values[medium]) {
          res = medium;
          upper = medium - 1;
        } else {
          lower = medium + 1;
        }
      }
      return res;
    }

    public static void swap(int[] values, int uIdx, int vIdx) {
      if (uIdx == vIdx) return;
      values[uIdx] ^= values[vIdx];
      values[vIdx] ^= values[uIdx];
      values[uIdx] ^= values[vIdx];
    }

    public static void shuffle(int[] values, int fromIdx, int toIdx) {
      for (int i = toIdx - fromIdx - 1; i > 0; --i) {
        swap(values, i + fromIdx, RANDOM.nextInt(i + 1) + fromIdx);
      }
    }

  }

  static class IntUtils {
    public static boolean isPow2(int n) {
      return n > 0 && (n & (n - 1)) == 0;
    }

    public static int nextPow2(int n) {
      if (n < 1) return 1;
      return isPow2(n) ? n : Integer.highestOneBit(n) << 1;
    }

  }

  static interface Displayable {
  }

  static class IntModular {
    private static final int MOD = 1000000007;
    public final int mod;
    private final int[] x;

    public IntModular() {
      this(MOD);
    }

    public IntModular(int mod) {
      this.mod = mod;
      this.x = new int[2];
    }

    public int add(int a, int b) {
      return fix(a + b);
    }

    public int fix(int a) {
      a = slightFix(a);
      return 0 <= a && a < mod ? a : slightFix(a % mod);
    }

    public int mul(int a, int b) {
      return a > 0
          ? (b < mod / a ? a * b : (int) ((long) a * b % mod))
          : 0;
    }

    private int slightFix(int a) {
      return a >= mod
          ? a - mod
          : a < 0 ? a + mod : a;
    }

  }
}