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

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

class TaskG {
    static class Intersector {
        long minxplusy = Long.MIN_VALUE;
        long maxxplusy = Long.MAX_VALUE;
        long minxminusy = Long.MIN_VALUE;
        long maxxminusy = Long.MAX_VALUE;

        void update(long kx, long ky, long a) {
            if (Math.abs(kx) != Math.abs(ky)) throw new RuntimeException();
            if (kx == 0) {
                if (a <= 0) return;
                minxplusy = Long.MAX_VALUE;
                maxxplusy = Long.MIN_VALUE;
                minxminusy = Long.MAX_VALUE;
                maxxminusy = Long.MIN_VALUE;
                return;
            }
            if (kx > 0) {
                if (ky > 0) {
                    maxxplusy = Math.min(maxxplusy, safeDivide(-a, kx));
                } else {
                    maxxminusy = Math.min(maxxminusy, safeDivide(-a, kx));
                }
            } else {
                if (ky < 0) {
                    minxplusy = Math.max(minxplusy, safeDivide(a + (-kx) - 1, -kx));
                } else {
                    minxminusy = Math.max(minxminusy, safeDivide(a + (-kx) - 1, -kx));
                }
            }
        }

        private long safeDivide(long a, long b) {
            if (a > 0) return a / b; else return (a - b + 1) / b;
        }
    }

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int l = in.nextInt();
        boolean[] know = new boolean[l + 1];
        long[] k = new long[l + 1];
        long[] ax = new long[l + 1];
        long[] ay = new long[l + 1];
        know[0] = true;
        know[l] = true;
        k[l] = 1;
        boolean knowP = false;
        long px = 0;
        long py = 0;
        for (int i = 0; i < n; ++i) {
            long t = in.nextLong();
            long x = in.nextLong();
            long y = in.nextLong();
            if ((x + y + t) % 2 != 0) {
                out.println("NO");
                return;
            }
            int when = (int) (t % l);
            long ck = -t / l;
            if (!know[when]) {
                know[when] = true;
                k[when] = ck;
                ax[when] = x;
                ay[when] = y;
            } else {
                if (knowP) {
                    if (k[when] * px + ax[when] != ck * px + x || Math.abs(k[when] * (double) px + ax[when] - ck * (double) px - x) > 1e62) {
                        out.println("NO");
                        return;
                    }
                    if (k[when] * py + ay[when] != ck * py + y || Math.abs(k[when] * (double) py + ay[when] - ck * (double) py - y) > 1e62) {
                        out.println("NO");
                        return;
                    }
                } else {
                    knowP = true;
                    long numx = x - ax[when];
                    long numy = y - ay[when];
                    long den = k[when] - ck;
                    if (numx % den != 0 || numy % den != 0) {
                        out.println("NO");
                        return;
                    }
                    px = numx / den;
                    py = numy / den;
                }
            }
        }

        {
            Intersector intersector = new Intersector();
            int prev = 0;
            for (int i = 1; i <= l; ++i) if (know[i]) {
                long dk = k[i] - k[prev];
                long dax = ax[i] - ax[prev];
                long day = ay[i] - ay[prev];
                for (int kx = -1; kx <= 1; kx += 2) {
                    for (int ky = -1; ky <= 1; ky += 2) {
                       intersector.update(kx * dk, ky * dk, kx * dax + ky * day - (i - prev));
                    }
                }
                prev = i;
            }
            if (knowP) {
                if (px + py < intersector.minxplusy || px + py > intersector.maxxplusy) {
                    out.println("NO");
                    return;
                }
                if (px - py < intersector.minxminusy || px - py > intersector.maxxminusy) {
                    out.println("NO");
                    return;
                }
            } else {
                if (intersector.minxplusy > intersector.maxxplusy) {
                    out.println("NO");
                    return;
                }
                if (intersector.minxminusy > intersector.maxxminusy) {
                    out.println("NO");
                    return;
                }
                long xplusy;
                if (intersector.minxplusy == Long.MIN_VALUE) {
                    if (intersector.maxxplusy == Long.MAX_VALUE) {
                        xplusy = 0;
                    } else {
                        xplusy = intersector.maxxplusy - 1;
                    }
                } else {
                    xplusy = intersector.minxplusy;
                }
                long xminusy;
                if (intersector.minxminusy == Long.MIN_VALUE) {
                    if (intersector.maxxminusy == Long.MAX_VALUE) {
                        xminusy = 0;
                    } else {
                        xminusy = intersector.maxxminusy - 1;
                    }
                } else {
                    xminusy = intersector.minxminusy;
                }
                if ((xplusy + xminusy) % 2 != 0) {
                    if (xplusy < intersector.maxxplusy) {
                        ++xplusy;
                    } else if (xminusy < intersector.maxxminusy) {
                        ++xminusy;
                    } else {
                        out.println("NO");
                        return;
                    }
                }
                px = (xplusy + xminusy) / 2;
                py = (xplusy - xminusy) / 2;
            }
        }

        int prev = 0;
        for (int i = 1; i <= l; ++i) if (know[i]) {
            long dk = k[i] - k[prev];
            long dax = ax[i] - ax[prev];
            long day = ay[i] - ay[prev];
            long dx = dk * px + dax;
            long dy = dk * py + day;
            if ((Math.abs(dx) + Math.abs(dy) > i - prev) || (Math.abs(dx) + Math.abs(dy) + (i - prev)) % 2 != 0) throw new RuntimeException();
            int extra = (int) ((i - prev - Math.abs(dx) - Math.abs(dy)) / 2);
            while (dx > 0) {
                out.print('R');
                --dx;
            }
            while (dx < 0) {
                out.print('L');
                ++dx;
            }
            while (dy > 0) {
                out.print('U');
                --dy;
            }
            while (dy < 0) {
                out.print('D');
                ++dy;
            }
            for (int j = 0; j < extra; ++j) {
                out.print("LR");
            }
            prev = i;
        }
        out.println();
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

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

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

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

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

}


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

public class F {
	static long mod = 1000000007;
	static long K;
	static long end;
	static long[] memo;
	public static void main(String[] args) throws Exception {
		FastScanner sc = new FastScanner(System.in);
		long A = sc.nextLong();
		long B = sc.nextLong();
		long SA = A;
		long SB = B;
		K = sc.nextLong();
		long LCM = 1;
		for(int a=2;a<=K;a++){
			LCM=LCM*a/GCD(LCM,a);
		}
		memo = new long[(int)(LCM+10)];
		long moves = 0;
		while(A%LCM!=0){
			A--;
		//	moves++;
		}
		while(B%LCM!=0){
			B++;
		//	moves++;
		}

		//System.out.println(B+"->"+A+" "+LCM);
		if(A<=SB){
		//	System.out.println("HERE");
			end = SB;
			Arrays.fill(memo,-1);
			moves = DP(SA-end);
		}
		else{
			end = 0;
			long gap = (A-B)/LCM;
			Arrays.fill(memo,-1);

			long size = DP(LCM);
			moves +=size*gap;
			end = SB;
		//	System.out.println(moves);
			Arrays.fill(memo,-1);

			moves += DP(B-end);
			end = A;
		//	System.out.println(moves);
			Arrays.fill(memo,-1);

			moves += DP(SA-end);
		}
		System.out.println(moves);
	}

	private static long DP(long cur) {
		if(cur==0)return 0;
		if(cur<0)return 99999;
		if(memo[(int)cur]!=-1)return memo[(int)cur];
		long ans = 1+DP(cur-1);
		for(int k=2;k<=K;k++){
			if((cur+end)%k!=0){
				ans=Math.min(ans,1+DP(cur-((cur+end)%k)));
			}
		}
		return memo[(int)cur]=ans;
	}

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

	static class FastScanner {

		BufferedReader br;

		StringTokenizer st;

		public FastScanner(InputStream in) throws Exception {

			br = new BufferedReader(new InputStreamReader(in));

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

		}

		public int numTokens() throws Exception {

			if (!st.hasMoreTokens()) {

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

				return numTokens();

			}

			return st.countTokens();

		}

		public String next() throws Exception {

			if (!st.hasMoreTokens()) {

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

				return next();

			}

			return st.nextToken();

		}

		public double nextDouble() throws Exception {

			return Double.parseDouble(next());

		}

		public float nextFloat() throws Exception {

			return Float.parseFloat(next());

		}

		public long nextLong() throws Exception {

			return Long.parseLong(next());

		}

		public int nextInt() throws Exception {

			return Integer.parseInt(next());

		}

		public String nextLine() throws Exception {

			return br.readLine().trim();

		}

	}
////

}


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

public class CF {
	static long mod = 1000000007;
	static long K;
	static long end;
	static long[] memo;
	public static void main(String[] args) throws Exception {
		FastScanner sc = new FastScanner(System.in);
		long A = sc.nextLong();
		long B = sc.nextLong();
		long SA = A;
		long SB = B;
		K = sc.nextLong();
		long LCM = 1;
		for(int a=2;a<=K;a++){
			LCM=LCM*a/GCD(LCM,a);
		}
		memo = new long[(int)(LCM+10)];
		long moves = 0;
		while(A%LCM!=0){
			A--;
		//	moves++;
		}
		while(B%LCM!=0){
			B++;
		//	moves++;
		}

		//System.out.println(B+"->"+A+" "+LCM);
		if(A<=SB){
		//	System.out.println("HERE");
			end = SB;
			Arrays.fill(memo,-1);
			moves = DP(SA-end);
		}
		else{
			end = 0;
			long gap = (A-B)/LCM;
			Arrays.fill(memo,-1);

			long size = DP(LCM);
			moves +=size*gap;
			end = SB;
		//	System.out.println(moves);
			Arrays.fill(memo,-1);

			moves += DP(B-end);
			end = A;
		//	System.out.println(moves);
			Arrays.fill(memo,-1);

			moves += DP(SA-end);
		}
		System.out.println(moves);
	}

	private static long DP(long cur) {
		if(cur==0)return 0;
		if(cur<0)return 99999;
		if(memo[(int)cur]!=-1)return memo[(int)cur];
		long ans = 1+DP(cur-1);
		for(int k=2;k<=K;k++){
			if((cur+end)%k!=0){
				ans=Math.min(ans,1+DP(cur-((cur+end)%k)));
			}
		}
		return memo[(int)cur]=ans;
	}

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

	static class FastScanner {

		BufferedReader br;

		StringTokenizer st;

		public FastScanner(InputStream in) throws Exception {

			br = new BufferedReader(new InputStreamReader(in));

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

		}

		public int numTokens() throws Exception {

			if (!st.hasMoreTokens()) {

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

				return numTokens();

			}

			return st.countTokens();

		}

		public String next() throws Exception {

			if (!st.hasMoreTokens()) {

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

				return next();

			}

			return st.nextToken();

		}

		public double nextDouble() throws Exception {

			return Double.parseDouble(next());

		}

		public float nextFloat() throws Exception {

			return Float.parseFloat(next());

		}

		public long nextLong() throws Exception {

			return Long.parseLong(next());

		}

		public int nextInt() throws Exception {

			return Integer.parseInt(next());

		}

		public String nextLine() throws Exception {

			return br.readLine().trim();

		}

	}

}


import java.util.*;
public class f {
public static void main(String[] args)
{
    Scanner input = new Scanner(System.in);
    long a = input.nextLong(), b = input.nextLong();
    int k = input.nextInt();
    int lcm = 1;
    for(int i = 2; i<=k; i++) lcm = lcm(lcm, i);
    int[] dp = new int[2*lcm];
    int start = (int)(a%lcm) + lcm;
    Arrays.fill(dp, 987654321);
    dp[start] = 0;
    for(int i = start; i>0; i--)
    {
        dp[i-1] = Math.min(dp[i-1], dp[i]+1);
        for(int j = 2; j<=k; j++)
        {
            int next = i - i%j;
            if(next >= 0) dp[next] = Math.min(dp[next], dp[i]+1);
        }
    }
    long res = 0;
    if(a-b >= lcm)
    {
        res = dp[lcm];
        a -= (a%lcm);
    }
    //System.out.println(dp[0]+" "+dp[lcm]);
    int lcmStep = dp[0]-dp[lcm];
    //System.out.println(lcm+" "+lcmStep);

    long numSteps = (a-b)/lcm - 2;
    if(numSteps > 0)
    {
        a -= lcm*numSteps;
        res += lcmStep*numSteps;
    }

    dp = new int[5*lcm];
    int end = (int)(b - lcm*(b/lcm));
    start = (int)(end + a - b);
    //System.out.println(start+" "+end);
    Arrays.fill(dp, 987654321);
    dp[start] = 0;
    for(int i = start; i>end; i--)
    {
        dp[i-1] = Math.min(dp[i-1], dp[i]+1);
        for(int j = 2; j<=k; j++)
        {
            int next = i - i%j;
            if(next > 0) dp[next] = Math.min(dp[next], dp[i]+1);
        }
    }

    res += dp[end];

    System.out.println(res);
}
static int lcm(int a, int b)
{
    return a/gcd(a,b)*b;
}
static int gcd(int a, int b)
{
    if(b==0) return a;
    return gcd(b, a%b);
}
}


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.IOException;
/**
 * Actual solution is at the top
 * @author  Tapan Sahni
 */

public class Tapan {
    public final  static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        //  Scanner in = new Scanner(inputStream);
        Reader in = new Reader();
        PrintWriter out = new PrintWriter(outputStream);
        Task_C solver = new Task_C();
        solver.solve( in, out);
        out.close();
    }
}
class Task_C {

    @SuppressWarnings("unused")

    public long step (long  a , long  b , long k){
        long ret = 0;
             while(a > b){
                 long Max = 1;
                 for(long i = 2 ;i<= k;i++ ){
                    long l1 = a%i;
                    if(a - l1 >= b)
                  Max = Math.max(Max, l1);
                 }
                 if(Max  == 0) Max = 1;
                 a-=Max;
                 ret++;
                }
             return ret;
    }
    public void solve(Reader in, PrintWriter out) throws IOException {
             long a = in.nextLong() , b = in.nextLong();
             long k = in.nextLong();
            long L = 360360L;
            if(a - b <= L) out.println(step(a , b , k));
            else{
             long ans = step(a%L , 0 , k);
             ans = ans + (long)step(L , 0 , k) * (a/L - b/L -1);
             ans = ans + (long)step(L ,b%L , k);
             out.println(ans);
          }
    }
}
class Reader {
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

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

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

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

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

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

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

    public char nextChar() throws IOException {
        byte c = read();
        while (c <= ' ')
            c = read();
        return (char) c;
    }

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

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

    public void close() throws IOException {
        if (din == null)
            return;
        din.close();
    }
}
class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

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

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

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

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


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

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

    static class TaskG {
        static final long MODULO = (long) (1e9 + 7);

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            String c = in.next();
            String d = in.next();
            int n = in.nextInt();
            long res = 0;
            long waysEqual = 0;
            if (c.length() == d.length()) {
                waysEqual = 1;
                for (int i = 0; i < c.length(); ++i) {
                    char ac = c.charAt(i);
                    char ad = d.charAt(i);
                    if (ac == '?') {
                        if (ad == '?') {
                            waysEqual = waysEqual * 2 % MODULO;
                        }
                    } else if (ad == '?') {

                    } else {
                        if (ac != ad) {
                            waysEqual = 0;
                            break;
                        }
                    }
                }
                long total = 1;
                for (int i = 0; i < n; ++i) {
                    total = total * 2 % MODULO;
                }
                total = ((total * 2 - 2) % MODULO + MODULO) % MODULO;
                res = (res + total * total % MODULO * waysEqual) % MODULO;
            }

            long[] nonperiodic = new long[n + 1];
            nonperiodic[0] = 1;
            for (int i = 1; i <= n; ++i) nonperiodic[i] = 2 * nonperiodic[i - 1] % MODULO;
            long[] uptoValid = new long[n + 1];
            for (int i = 1; i <= n; ++i) {
                uptoValid[i] = uptoValid[i - 1] + nonperiodic[i];
            }
            for (int i = 1; i <= n; ++i) {
                for (int j = 2 * i; j <= n; j += i) {
                    nonperiodic[j] -= nonperiodic[i];
                    if (nonperiodic[j] < 0) nonperiodic[j] += MODULO;
                }
            }

            long anyValid = 0;
            for (int i = 1; i <= n; ++i) {
                long maxTimes = n / i;
                anyValid = (anyValid + nonperiodic[i] * maxTimes % MODULO * maxTimes) % MODULO;
            }

            int na = 0;
            int nb = 0;
            int qPlus = 0;
            int qMinus = 0;
            for (int i = 0; i < c.length(); ++i) {
                char ac = c.charAt(i);
                if (ac == 'A') ++na;
                else if (ac == 'B') ++nb;
                else ++qPlus;
            }
            for (int i = 0; i < d.length(); ++i) {
                char ad = d.charAt(i);
                if (ad == 'A') --na;
                else if (ad == 'B') --nb;
                else ++qMinus;
            }
            na -= qMinus;
            qPlus += qMinus;
            qMinus = 0;
            long[] invs = new long[qPlus + 1];
            if (qPlus > 0)
                invs[1] = 1;
            for (int i = 2; i <= qPlus; ++i) {
                invs[i] = (MODULO - invs[((int) (MODULO % i))] * (MODULO / i) % MODULO) % MODULO;
                if (invs[i] * i % MODULO != 1) throw new RuntimeException();
            }
            long comb = 1;
            for (int nPlus = 0; nPlus <= qPlus; ++nPlus) {
                if (nPlus > 0) {
                    comb = comb * (qPlus - nPlus + 1) % MODULO * invs[nPlus] % MODULO;
                }
                int deltaMul = na + nPlus;
                int bMul = c.length() - d.length();
                if (deltaMul == 0 && bMul == 0) {
                    res = ((res + (comb - waysEqual) * anyValid) % MODULO + MODULO) % MODULO;
                } else {
                    int g = gcd(Math.abs(deltaMul), Math.abs(bMul));
                    deltaMul /= g;
                    bMul /= g;
                    if (deltaMul != 0) {
                        if (deltaMul < 0) {
                            deltaMul = -deltaMul;
                            bMul = -bMul;
                        }
                        int lb = deltaMul;
                        int la = lb - bMul;
                        if (la > 0) {
                            res = (res + comb * uptoValid[n / Math.max(la, lb)]) % MODULO;
                        }
                    }
                }
            }

            out.println(res);
        }

        private int gcd(int a, int b) {
            while (b > 0) {
                int t = a % b;
                a = b;
                b = t;
            }
            return a;
        }

    }

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

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

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

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

    }
}


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

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

    static class TaskG {
        static final long MODULO = (long) (1e9 + 7);

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            String c = in.next();
            String d = in.next();
            int n = in.nextInt();
            long res = 0;
            long waysEqual = 0;
            if (c.length() == d.length()) {
                waysEqual = 1;
                for (int i = 0; i < c.length(); ++i) {
                    char ac = c.charAt(i);
                    char ad = d.charAt(i);
                    if (ac == '?') {
                        if (ad == '?') {
                            waysEqual = waysEqual * 2 % MODULO;
                        }
                    } else if (ad == '?') {

                    } else {
                        if (ac != ad) {
                            waysEqual = 0;
                            break;
                        }
                    }
                }
                long total = 1;
                for (int i = 0; i < n; ++i) {
                    total = total * 2 % MODULO;
                }
                total = ((total * 2 - 2) % MODULO + MODULO) % MODULO;
                res = (res + total * total % MODULO * waysEqual) % MODULO;
            }

            long[] nonperiodic = new long[n + 1];
            nonperiodic[0] = 1;
            for (int i = 1; i <= n; ++i) nonperiodic[i] = 2 * nonperiodic[i - 1] % MODULO;
            long[] uptoValid = new long[n + 1];
            for (int i = 1; i <= n; ++i) {
                uptoValid[i] = uptoValid[i - 1] + nonperiodic[i];
                uptoValid[i] %= MODULO;
            }
            for (int i = 1; i <= n; ++i) {
                for (int j = 2 * i; j <= n; j += i) {
                    nonperiodic[j] -= nonperiodic[i];
                    if (nonperiodic[j] < 0) nonperiodic[j] += MODULO;
                }
            }

            long anyValid = 0;
            for (int i = 1; i <= n; ++i) {
                long maxTimes = n / i;
                anyValid = (anyValid + nonperiodic[i] * maxTimes % MODULO * maxTimes) % MODULO;
            }

            int na = 0;
            int nb = 0;
            int qPlus = 0;
            int qMinus = 0;
            for (int i = 0; i < c.length(); ++i) {
                char ac = c.charAt(i);
                if (ac == 'A') ++na;
                else if (ac == 'B') ++nb;
                else ++qPlus;
            }
            for (int i = 0; i < d.length(); ++i) {
                char ad = d.charAt(i);
                if (ad == 'A') --na;
                else if (ad == 'B') --nb;
                else ++qMinus;
            }
            na -= qMinus;
            qPlus += qMinus;
            qMinus = 0;
            long[] invs = new long[qPlus + 1];
            if (qPlus > 0)
                invs[1] = 1;
            for (int i = 2; i <= qPlus; ++i) {
                invs[i] = (MODULO - invs[((int) (MODULO % i))] * (MODULO / i) % MODULO) % MODULO;
                if (invs[i] * i % MODULO != 1) throw new RuntimeException();
            }
            long comb = 1;
            for (int nPlus = 0; nPlus <= qPlus; ++nPlus) {
                if (nPlus > 0) {
                    comb = comb * (qPlus - nPlus + 1) % MODULO * invs[nPlus] % MODULO;
                }
                int deltaMul = na + nPlus;
                int bMul = c.length() - d.length();
                if (deltaMul == 0 && bMul == 0) {
                    res = ((res + (comb - waysEqual) * anyValid) % MODULO + MODULO) % MODULO;
                } else {
                    int g = gcd(Math.abs(deltaMul), Math.abs(bMul));
                    deltaMul /= g;
                    bMul /= g;
                    if (deltaMul != 0) {
                        if (deltaMul < 0) {
                            deltaMul = -deltaMul;
                            bMul = -bMul;
                        }
                        int lb = deltaMul;
                        int la = lb - bMul;
                        if (la > 0) {
                            res = (res + comb * uptoValid[n / Math.max(la, lb)]) % MODULO;
                        }
                    }
                }
            }

            out.println(res);
        }

        private int gcd(int a, int b) {
            while (b > 0) {
                int t = a % b;
                a = b;
                b = t;
            }
            return a;
        }

    }

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

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

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

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

    }
}


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

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

    static class TaskG {
        static final long MODULO = (long) (1e9 + 7);

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            String c = in.next();
            String d = in.next();
            int n = in.nextInt();
            long res = 0;
            long waysEqual = 0;
            if (c.length() == d.length()) {
                waysEqual = 1;
                for (int i = 0; i < c.length(); ++i) {
                    char ac = c.charAt(i);
                    char ad = d.charAt(i);
                    if (ac == '?') {
                        if (ad == '?') {
                            waysEqual = waysEqual * 2 % MODULO;
                        }
                    } else if (ad == '?') {

                    } else {
                        if (ac != ad) {
                            waysEqual = 0;
                            break;
                        }
                    }
                }
                long total = 1;
                for (int i = 0; i < n; ++i) {
                    total = total * 2 % MODULO;
                }
                total = ((total * 2 - 2) % MODULO + MODULO) % MODULO;
                res = (res + total * total % MODULO * waysEqual) % MODULO;
            }

            long[] nonperiodic = new long[n + 1];
            nonperiodic[0] = 1;
            for (int i = 1; i <= n; ++i) nonperiodic[i] = 2 * nonperiodic[i - 1] % MODULO;
            long[] uptoValid = new long[n + 1];
            for (int i = 1; i <= n; ++i) {
                uptoValid[i] = uptoValid[i - 1] + nonperiodic[i];
                uptoValid[i] %= MODULO;
            }
            for (int i = 1; i <= n; ++i) {
                for (int j = 2 * i; j <= n; j += i) {
                    nonperiodic[j] -= nonperiodic[i];
                    if (nonperiodic[j] < 0) nonperiodic[j] += MODULO;
                }
            }

            long anyValid = 0;
            for (int i = 1; i <= n; ++i) {
                long maxTimes = n / i;
                anyValid = (anyValid + nonperiodic[i] * maxTimes % MODULO * maxTimes) % MODULO;
            }

            int na = 0;
            int nb = 0;
            int qPlus = 0;
            int qMinus = 0;
            for (int i = 0; i < c.length(); ++i) {
                char ac = c.charAt(i);
                if (ac == 'A') ++na;
                else if (ac == 'B') ++nb;
                else ++qPlus;
            }
            for (int i = 0; i < d.length(); ++i) {
                char ad = d.charAt(i);
                if (ad == 'A') --na;
                else if (ad == 'B') --nb;
                else ++qMinus;
            }
            na -= qMinus;
            qPlus += qMinus;
            qMinus = 0;
            long[] invs = new long[qPlus + 1];
            if (qPlus > 0)
                invs[1] = 1;
            for (int i = 2; i <= qPlus; ++i) {
                invs[i] = (MODULO - invs[((int) (MODULO % i))] * (MODULO / i) % MODULO) % MODULO;
                if (invs[i] * i % MODULO != 1) throw new RuntimeException();
            }
            long comb = 1;
            for (int nPlus = 0; nPlus <= qPlus; ++nPlus) {
                if (nPlus > 0) {
                    comb = comb * (qPlus - nPlus + 1) % MODULO * invs[nPlus] % MODULO;
                }
                int deltaMul = na + nPlus;
                int bMul = c.length() - d.length();
                if (deltaMul == 0 && bMul == 0) {
                    res = ((res + (comb - waysEqual) * anyValid) % MODULO + MODULO) % MODULO;
                } else {
                    int g = gcd(Math.abs(deltaMul), Math.abs(bMul));
                    deltaMul /= g;
                    bMul /= g;
                    if (deltaMul != 0) {
                        if (deltaMul < 0) {
                            deltaMul = -deltaMul;
                            bMul = -bMul;
                        }
                        int lb = deltaMul;
                        int la = lb - bMul;
                        if (la > 0) {
                            res = (res + comb * uptoValid[n / Math.max(la, lb)]) % MODULO;
                        }
                    }
                }
            }

            out.println(res);
        }

        private int gcd(int a, int b) {
            while (b > 0) {
                int t = a % b;
                a = b;
                b = t;
            }
            return a;
        }

    }

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

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

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

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

    }
}


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

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

class TaskD2 {

    final long MOD = 1_000_003;

    long binPow(long x, long n) {
        long res = 1;
        while (n > 0) {
            if (n % 2 == 1)
                res = res * x % MOD;
            x = x * x % MOD;
            n /= 2;
        }
        return res;
    }

    long inv(long x) {
        return binPow(x, MOD - 2);
    }

    long fac(long n) {
        long res = 1;
        for (int i = 1; i <= n; i++)
            res = res * i % MOD;
        return res;
    }

    public void solve(int testNumber, FastScanner in, PrintWriter out) {
        int n = in.nextInt();
        int k = in.nextInt();
        long res = fac(n + k);
        res = res * inv(fac(k)) % MOD;
        res = res * inv(fac(n)) % MOD;
        out.println((res - 1 + MOD) % MOD);
    }
}

class FastScanner {
    private StringTokenizer tokenizer;
    private BufferedReader reader;

    public FastScanner(InputStream inputStream) {
        reader = new BufferedReader(new InputStreamReader(inputStream));
    }

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

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

}


import static java.lang.Double.parseDouble;
import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.System.exit;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.StringTokenizer;

public class D2 {

	static BufferedReader in;
	static PrintWriter out;
	static StringTokenizer tok;

	static final int MOD = 1000003;

	static int sub(int a, int b) {
		int res = a - b;
		if (res < 0) {
			res += MOD;
		}
		return res;
	}

	static int mul(int a, int b) {
		return (int) ((long) a * b % MOD);
	}

	static int inv(int a) {
		return BigInteger.valueOf(a).modInverse(BigInteger.valueOf(MOD)).intValue();
	}

	static void solve() throws Exception {
		int n = nextInt();
		int c = nextInt();
		int num = 1, den = 1;
		for (int i = 0; i < c; i++) {
			num = mul(num, n + i + 1);
			den = mul(den, i + 1);
		}
		out.print(sub(mul(num, inv(den)), 1));
	}

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

	static long nextLong() throws IOException {
		return parseLong(next());
	}

	static double nextDouble() throws IOException {
		return parseDouble(next());
	}

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

	public static void main(String[] args) {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(new OutputStreamWriter(System.out));
			solve();
			in.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			exit(1);
		}
	}
}


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

public class HelveticqE {

    static final int mod = (int)1e6 + 3;

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in);
        PrintWriter w = new PrintWriter(System.out);

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

        long fact[] = new long[n + c + 2];
        fact[0] = 1;
        for (int i = 1; i < fact.length; i++)
            fact[i] = (fact[i - 1] * i) % mod;

        long ans = fact[n + c];
        ans *= pow(fact[n], mod - 2);
        ans %= mod;
        ans *= pow(fact[c], mod - 2);
        ans %= mod;
        ans -= 1;
        ans += mod;
        ans %= mod;

        w.println(ans);
        w.close();
    }

    static long pow(long a, int b) {
        if (b == 0)
            return 1;
        long t = pow(a, b >> 1);
        t = (t * t) % mod;
        if(b % 2 == 1)
            t = (t * a) % mod;
        return t;
    }
    static class InputReader {

        private final InputStream stream;
        private final byte[] buf = new byte[8192];
        private int curChar, snumChars;
        private SpaceCharFilter filter;

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

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

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

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

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

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

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

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);
        }
    }
}


//Created by Aminul on 4/3/2019.

import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;

public class CF690D2 {
    public static void main(String[] args) throws Exception {
        Scanner in = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        int n = in.nextInt(), m = in.nextInt();
        initialize(n + m + 10);
        long ans = 0;
        for (int i = 1; i <= m; i++) {
            ans = (ans + nCr(n + i - 1, i)) % mod;
        }
        pw.println(ans);
        pw.close();
    }

    static long f[], inv[], mod = (int) 1e6 + 3;

    static void initialize(int n) {
        f = new long[n + 1];
        f[0] = 1;
        for (int i = 1; i <= n; i++) {
            f[i] = (f[i - 1] * i) % mod;
        }
        inv = new long[n + 1];
        inv[n] = BigInteger.valueOf(f[n]).modInverse(BigInteger.valueOf(mod)).longValue();
        for (int i = n - 1; i >= 0; i--) {
            inv[i] = (inv[i + 1] * (i + 1)) % mod;
        }
    }

    static long nCr(int n, int c) {
        long u = f[n], d = (inv[c] * inv[n - c]) % mod;
        return (u * d) % mod;
    }

    static void debug(Object...obj) {
        System.err.println(Arrays.deepToString(obj));
    }
}


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

public class Main{

	public static void main(String args[]) throws IOException{
		new Main().mains();
	}

	public int P[],move_range[],throw_range[],ans,name[][];
	public boolean F[];
	//0-2能否移动 0可以举人 1举了小的 2举了大的 3已经扔出去

	int sta_num(int statue){
		int ret = (P[1] - 1) + (P[2] - 1) * 42 + (P[3] - 1) * 42 * 42;
		return ret + statue * 42 * 42 * 42;
	}

	int num(int a, int b){
		if (b == 0) return (a == 1) ? (2) : (1);
		return (a == 3) ? (2) : (3);
	}

	void DFS(int statue){
		ans = Math.max(ans, Math.max(Math.max(P[3], P[1]), P[2]));
		if (F[sta_num(statue)] == true) return;
		F[sta_num(statue)] = true;
		int foru[] = new int[4];
		/*int check[] = new int[4];
		for (int i = 1; i <= 3; i ++) check[i] = P[i];*/
		boolean be_throwed[] = new boolean[4];
		for (int mv = 1; mv <= 3; mv ++)
			be_throwed[mv] = false;
		for (int mv = 1; mv <= 3; mv ++){
			foru[mv] = (statue >> (3 + (mv - 1) * 2)) % 4;
			if (foru[mv] >= 1 && foru[mv] <= 2)
				be_throwed[num(mv, foru[mv] - 1)] = true;
		}
		for (int i = 1; i <= 3; i ++)
			if ((statue & (1 << (i - 1))) == 0 && (foru[i] == 0 || foru[i] == 3)){
				for (int step = -move_range[i]; step <= move_range[i]; step ++){
					if (step + P[i] < 1) continue;
					boolean could = true;
					for (int j = 1; j <= 3; j ++)
						if (step + P[i] == P[j])
							could = false;
					if (could == false) continue;
					P[i] += step;
					DFS(statue | (1 << (i - 1)));
					P[i] -= step;
				}
			}
		for (int i = 1; i <= 3; i ++){
			for (int j = 1; j <= 3; j ++)
				if (i != j && Math.abs(P[i] - P[j]) == 1 && be_throwed[j] == false && foru[i] == 0 && be_throwed[i] == false){
					int diff = 6 - i - j;
					int temp[] = new int[4],newsta = statue | ((1 << ((2 * i - 2) + 3)) * (name[i][j] + 1));
					temp[1] = P[1]; temp[2] = P[2]; temp[3] = P[3];
					P[j] = P[i];
					if (be_throwed[diff] == true) P[diff] = P[i];
					DFS(newsta);
					P[1] = temp[1]; P[2] = temp[2]; P[3] = temp[3];
				}
			if (be_throwed[i] == false && foru[i] >= 1 && foru[i] <= 2){
				int j = num(i, foru[i] - 1), diff = 6 - i - j;
				int xor = ((1 << (2 * i - 2) + 3) * (foru[i]));
				for (int step = -throw_range[i]; step <= throw_range[i]; step ++) if (step != 0){
					int temp[] = new int[4],newsta = (statue ^ xor) | (3 * (1 << ((2 * i - 2) + 3)));
					temp[1] = P[1]; temp[2] = P[2]; temp[3] = P[3];
					P[j] = P[i] + step;
					if (be_throwed[diff] == true) P[diff] = P[i] + step;
					DFS(newsta);
					P[1] = temp[1]; P[2] = temp[2]; P[3] = temp[3];
				}
			}
		}
	}

	public void solve() throws IOException{
		P = new int[4];
		move_range = new int[4];
		throw_range = new int[4];
		name = new int[5][5];
		name[1][3] = name[2][3] = name[3][2] = 1;
		F = new boolean[(42 * 8) * (42 * 8) * (42 * 8) + 100];
		for (int i = 1; i <= 3; i ++){
			P[i] = nextInt();
			move_range[i] = nextInt();
			throw_range[i] = nextInt();
		}
		DFS(0);
		out.println(ans);
	}

	void mains() throws IOException{
		reader = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(new OutputStreamWriter(System.out));
		tokenizer = null;
		//File fin = new File("a.in");
		//reader = new BufferedReader(new InputStreamReader(new FileInputStream(fin)));
		//out = new PrintWriter("a.out");
		solve();
		reader.close();
		out.flush();
	}

	BufferedReader reader;
	StringTokenizer tokenizer;
	PrintWriter out;
	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}
	long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}
	double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}
	String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

}


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

public class Main{

	public static void main(String args[]) throws IOException{
		new Main().mains();
	}

	public int P[],move_range[],throw_range[],ans,name[][];
	public boolean F[];
	//0-2能否移动 0可以举人 1举了小的 2举了大的 3已经扔出去

	int sta_num(int statue){
		int ret = (P[1] - 1) + (P[2] - 1) * 42 + (P[3] - 1) * 42 * 42;
		return ret + statue * 42 * 42 * 42;
	}

	int num(int a, int b){
		if (b == 0) return (a == 1) ? (2) : (1);
		return (a == 3) ? (2) : (3);
	}

	void DFS(int statue){
		ans = Math.max(ans, Math.max(Math.max(P[3], P[1]), P[2]));
		if (Math.max(Math.max(P[3], P[1]), P[2]) == 17){
			int nis = 33;
			nis = 1;
		}
		if (F[sta_num(statue)] == true) return;
		F[sta_num(statue)] = true;
		int foru[] = new int[4];
		int check[] = new int[4];
		for (int i = 1; i <= 3; i ++) check[i] = P[i];
		boolean be_throwed[] = new boolean[4];
		for (int mv = 1; mv <= 3; mv ++)
			be_throwed[mv] = false;
		for (int mv = 1; mv <= 3; mv ++){
			foru[mv] = (statue >> (3 + (mv - 1) * 2)) % 4;
			if (foru[mv] >= 1 && foru[mv] <= 2)
				be_throwed[num(mv, foru[mv] - 1)] = true;
		}
		for (int i = 1; i <= 3; i ++)
			if ((statue & (1 << (i - 1))) == 0 && (foru[i] == 0 || foru[i] == 3)){
				for (int step = -move_range[i]; step <= move_range[i]; step ++){
					if (step + P[i] < 1) continue;
					boolean could = true;
					for (int j = 1; j <= 3; j ++)
						if (step + P[i] == P[j])
							could = false;
					if (could == false) continue;
					P[i] += step;
					DFS(statue | (1 << (i - 1)));
					P[i] -= step;
				}
			}
		for (int i = 1; i <= 3; i ++){
			for (int j = 1; j <= 3; j ++)
				if (i != j && Math.abs(P[i] - P[j]) == 1 && be_throwed[j] == false && foru[i] == 0 && be_throwed[i] == false){
					int diff = 6 - i - j;
					int temp[] = new int[4],newsta = statue | ((1 << ((2 * i - 2) + 3)) * (name[i][j] + 1));
					temp[1] = P[1]; temp[2] = P[2]; temp[3] = P[3];
					P[j] = P[i];
					if (be_throwed[diff] == true) P[diff] = P[i];
					DFS(newsta);
					P[1] = temp[1]; P[2] = temp[2]; P[3] = temp[3];
				}
			if (be_throwed[i] == false && foru[i] >= 1 && foru[i] <= 2){
				int j = num(i, foru[i] - 1), diff = 6 - i - j;
				int xor = ((1 << (2 * i - 2) + 3) * (foru[i]));
				for (int step = -throw_range[i]; step <= throw_range[i]; step ++) if (step != 0){
					int temp[] = new int[4],newsta = (statue ^ xor) | (3 * (1 << ((2 * i - 2) + 3)));
					temp[1] = P[1]; temp[2] = P[2]; temp[3] = P[3];
					P[j] = P[i] + step;
					if (be_throwed[diff] == true) P[diff] = P[i] + step;
					DFS(newsta);
					P[1] = temp[1]; P[2] = temp[2]; P[3] = temp[3];
				}
			}
		}
	}

	public void solve() throws IOException{
		P = new int[4];
		move_range = new int[4];
		throw_range = new int[4];
		name = new int[5][5];
		name[1][3] = name[2][3] = name[3][2] = 1;
		F = new boolean[(42 * 8) * (42 * 8) * (42 * 8) + 100];
		for (int i = 1; i <= 3; i ++){
			P[i] = nextInt();
			move_range[i] = nextInt();
			throw_range[i] = nextInt();
		}
		DFS(0);
		out.println(ans);
	}

	void mains() throws IOException{
		reader = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(new OutputStreamWriter(System.out));
		tokenizer = null;
		//File fin = new File("a.in");
		//reader = new BufferedReader(new InputStreamReader(new FileInputStream(fin)));
		//out = new PrintWriter("a.out");
		solve();
		reader.close();
		out.flush();
	}

	BufferedReader reader;
	StringTokenizer tokenizer;
	PrintWriter out;
	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}
	long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}
	double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}
	String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

}


import java.util.*;
import java.math.*;
import static java.lang.Character.isDigit;
import static java.lang.Character.isLowerCase;
import static java.lang.Character.isUpperCase;
import static java.lang.Math.*;
import static java.math.BigInteger.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;
import static java.lang.Character.isDigit;

public class Main{

    void run(){
        Cond cond = new Cond();
        System.out.println(doit(cond));
    }
    HashMap<Cond,Integer> map=new HashMap<Cond,Integer>();
    private int doit(Cond cond){
        if(map.containsKey(cond))return map.get(cond);
        List<Cond> allNexts = cond.allNexts();
        int res=cond.getMaxX();
        for(Cond c:allNexts) {
            res = max(res,doit(c));
        }
        map.put(cond,res);
        return res;
    }
    interface Command{
        boolean doit();
        void undo();
    }
    class Move implements Command{
        Person p;
        int x;
        Move(Person p,int x){
            this.p=p;
            this.x=x;
        }
        public boolean doit(){
            if(p.moved || p.lifted || p.lifting!=null)return false;
            p.x += x;
            p.moved=true;
            return true;
        }
        public void undo(){
            assert p.moved && !p.lifted && p.lifting==null;
            p.x-=x;
            p.moved=false;
        }
    }
    class Lift implements Command{
        Person p,q;
        Lift(Person p,Person q){
            this.p=p;this.q=q;
        }
        int from;
        public boolean doit(){
            if(q.lifted || p.lifted || p.lifting!=null || p.throwed)return false;
            if(abs(p.x-q.x)!=1)return false;
            from = q.x;
            q.x=p.x;
            if(q.lifting!=null)q.lifting.x=p.x;
            p.lifting=q;
            q.lifted = true;
            return true;
        }
        public void undo(){
            assert p.lifting==q && q.lifted && q.x==p.x;
            q.x=from;
            if(q.lifting!=null)q.lifting.x=from;
            p.lifting=null;
            q.lifted=false;
        }
    }

    class Throw implements Command{
        Person p;
        int x;
        Throw(Person p,int x){
            this.p=p;
            this.x=x;
        }
        Person q;
        public boolean doit(){
            if(p.lifted || p.lifting==null)return false;
            q=p.lifting;
            assert q.x==p.x;
            assert q.x==p.x && !p.throwed;
            assert q.x==p.x && !p.throwed && q.lifted;
            p.lifting=null;
            p.throwed=true;
            q.lifted=false;
            q.x += x;
            if(q.lifting!=null)q.lifting.x += x;
            return true;
        }

        public void undo(){
            assert p.lifting==null && p.throwed && !q.lifted && q.x==p.x+x;
            p.lifting=q;
            p.throwed=false;
            q.lifted=true;
            q.x -= x;
            if(q.lifting!=null)q.lifting.x -= x;
        }
    }

    class Cond{
        Person[] ps;
        Cond(){
            ps=new Person[3];
            for(int i=0;i<3;i++)ps[i]=new Person(nextInt(),nextInt(),nextInt());
        }
        Cond(Person[]ps){
            this.ps=ps;
        }
        public List<Cond> allNexts(){
            ArrayList<Cond> list=new ArrayList<Cond>();
            Cond now = this.myClone();
            for(Person p:ps) {
                assert p!=null;
                for(int i=-p.maxMove;i<=p.maxMove;i++) {
                    Command c = new Move(p,i);
                    if(c.doit()) {
                        list.add(this.myClone());
                        c.undo();
                        assert now.equals(this);
                    }
                }
                for(Person q:ps)if(p!=q) {
                    Command c = new Lift(p,q);
                    if(c.doit()) {
                        list.add(this.myClone());
                        c.undo();
                        assert now.equals(this);
                    }
                }
                for(int i=-p.power;i<=p.power;i++) {
                    Command c = new Throw(p,i);
                    Person q = p.lifting;
                    if(c.doit()) {
                        assert asList(ps).contains(q);
                        list.add(this.myClone());
                        c.undo();
                        assert now.equals(this);
                    }
                }
            }
            return list;
        }
        private Cond myClone(){
            Person[] qs = new Person[3];
            int cnt=0;
            for(;;) {
                for(int i=0;i<3;i++)if(qs[i]==null) {
                    if(ps[i].lifting==null) {
                        cnt++;
                        qs[i]=ps[i].myClone();
                    }
                    else {
                        if(asList(qs).contains(ps[i].lifting)) {
                            cnt++;
                            Person q = ps[i].myClone();
                            q.lifting = asList(qs).get(asList(qs).indexOf(q.lifting));
                            assert q.lifting.x == q.x;
                            qs[i]=q;
                        }
                    }
                }
                if(cnt==3)break;
            }
            Cond cond = new Cond(qs);
            return cond;
        }

        public String toString(){
            return "Cond [ps="+Arrays.toString(ps)+"]";
        }
        public int getMaxX(){
            int res=0;
            for(Person p:ps)res = max(res,p.x);
            return res;
        }
        public int hashCode(){
            final int prime=31;
            int result=1;
            result=prime*result+getOuterType().hashCode();
            result=prime*result+Arrays.hashCode(ps);
            return result;
        }
        public boolean equals(Object obj){
            if(this==obj) return true;
            if(obj==null) return false;
            if(getClass()!=obj.getClass()) return false;
            Cond other=(Cond)obj;
            if(!getOuterType().equals(other.getOuterType())) return false;
            if(!Arrays.equals(ps,other.ps)) return false;
            return true;
        }
        private Main getOuterType(){
            return Main.this;
        }
    }

    class Person {

        public String toString(){
            return "Person [lifted="+lifted+", lifting="+lifting+", maxMove="+maxMove+", moved="+moved+", power="+power
                +", throwed="+throwed+", x="+x+"]";
        }
        boolean moved;
        Person lifting;
        boolean throwed;
        boolean lifted;
        int x;
        int power;
        int maxMove;

        public Person myClone(){
            return new Person(moved,lifting==null ? null : lifting.myClone(),throwed,lifted,x,power,maxMove);
        }

        private Person(boolean moved,Person lifting,boolean throwed,boolean lifted,int x,int power,int maxMove){
            super();
            this.moved=moved;
            this.lifting=lifting;
            this.throwed=throwed;
            this.lifted=lifted;
            this.x=x;
            this.power=power;
            this.maxMove=maxMove;
        }

        public Person(int x,int maxMove,int power){
            this.x=x;
            this.maxMove=maxMove;
            this.power=power;
        }

        public int hashCode(){
            final int prime=31;
            int result=1;
            result=prime*result+getOuterType().hashCode();
            result=prime*result+(lifted?1231:1237);
            result=prime*result+((lifting==null)?0:lifting.hashCode());
            result=prime*result+maxMove;
            result=prime*result+(moved?1231:1237);
            result=prime*result+power;
            result=prime*result+(throwed?1231:1237);
            result=prime*result+x;
            return result;
        }
        public boolean equals(Object obj){
            if(this==obj) return true;
            if(obj==null) return false;
            if(getClass()!=obj.getClass()) return false;
            Person other=(Person)obj;
            if(!getOuterType().equals(other.getOuterType())) return false;
            if(lifted!=other.lifted) return false;
            if(lifting==null){
                if(other.lifting!=null) return false;
            }else if(!lifting.equals(other.lifting)) return false;
            if(maxMove!=other.maxMove) return false;
            if(moved!=other.moved) return false;
            if(power!=other.power) return false;
            if(throwed!=other.throwed) return false;
            if(x!=other.x) return false;
            return true;
        }
        private Main getOuterType(){
            return Main.this;
        }

    }

    int nextInt(){
        try{
            int c=System.in.read();
            if(c==-1) return c;
            while(c!='-'&&(c<'0'||'9'<c)){
                c=System.in.read();
                if(c==-1) return c;
            }
            if(c=='-') return -nextInt();
            int res=0;
            do{
                res*=10;
                res+=c-'0';
                c=System.in.read();
            }while('0'<=c&&c<='9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }

    long nextLong(){
        try{
            int c=System.in.read();
            if(c==-1) return -1;
            while(c!='-'&&(c<'0'||'9'<c)){
                c=System.in.read();
                if(c==-1) return -1;
            }
            if(c=='-') return -nextLong();
            long res=0;
            do{
                res*=10;
                res+=c-'0';
                c=System.in.read();
            }while('0'<=c&&c<='9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }

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

    String next(){
        try{
            StringBuilder res=new StringBuilder("");
            int c=System.in.read();
            while(Character.isWhitespace(c))
                c=System.in.read();
            do{
                res.append((char)c);
            }while(!Character.isWhitespace(c=System.in.read()));
            return res.toString();
        }catch(Exception e){
            return null;
        }
    }

    String nextLine(){
        try{
            StringBuilder res=new StringBuilder("");
            int c=System.in.read();
            while(c=='\r'||c=='\n')
                c=System.in.read();
            do{
                res.append((char)c);
                c=System.in.read();
            }while(c!='\r'&&c!='\n');
            return res.toString();
        }catch(Exception e){
            return null;
        }
    }
    public static void main(String[] args){
        new Main().run();
    }
}


package round72;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;

// 問題文を読んだら必ずサンプルでためせ ！
// あせってsubmitするな！！
// intあふれはないか！！
// コーナーケース(最小, 最大, 特殊なケース)で試したか！！
// 余りを求める問題で、マイナスになってはいないか！！
// 初期化をしているか！！
// すべての出力パターンをチェックしたか！！
public class E {
	Scanner in;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
	}

	void run() throws Exception
	{
		in = INPUT.isEmpty() ? new Scanner(System.in) : new Scanner(INPUT);
		out = new PrintWriter(System.out);

		solve();
		out.flush();
	}

	public static void main(String[] args) throws Exception
	{
		new E().run();
	}

	int ni() { return Integer.parseInt(in.next()); }
	double nd() { return Double.parseDouble(in.next()); }
	void tr(Object... o) { if(INPUT.length() != 0)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.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;
        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.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;
    }

  }
}