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

  }
}