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

// NEW WAY here, OLD WAY down below

public class B {

    // 40 lines of main for this specific exercise
    // ..using general purpose library "Binary"

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        long a = scanner.nextLong();
        long b = scanner.nextLong();
        Binary bin = new Binary(Long.toBinaryString(a));
        Binary goal = new Binary(Long.toBinaryString(b));

        // If too many zeroes, block out least remarkable ones
        int zeroCount = 0;
        for (int i=bin.length-1; i>=0; i--) {
            if (bin.get(i) == '0') zeroCount++;
        }
        for (int i=bin.length-1; i>=0 && zeroCount > 1; i--) {
            if (bin.get(i) != '0') continue;
            bin.set(i, '1');
            zeroCount--;
        }
        // If not enough
        if (zeroCount == 0) {
            bin.addFirst('1');
            bin.set(1, '0');
        }

        // Jump through and count binaries with one '0'
        int count = 0;
        int i = 1;
        while (bin.compareTo(goal) <= 0) {
            count++;
            while (bin.get(i) != '0') {
                i++;
            }

            // Modify bin to get next binary with one '0'
            bin.set(i, '1');
            i++;
            if (i >= bin.length) {
                bin.addFirst('1');
                i = 1;
            }
            bin.set(i, '0');
        }
        System.out.println(count);
        scanner.close();
    }

    public static void mainExample(String[] args) {
        Long n = 9891372933152L;
        String binaryString = Long.toBinaryString(n);
        Binary b = new Binary(binaryString);
    }

}

/**
 * When manipulating small binary strings, instantiate new Binary(string)
 * When just reading large binary strings, instantiate new Binary(string,true).
 */
class Binary implements Comparable<Binary> {
    private boolean[] d;
    private int first; // Starting from left, the first (most remarkable) '1'
    public int length;

    public Binary(String binaryString) {
        this(binaryString, false);
    }
    public Binary(String binaryString, boolean limitSize) {
        length = binaryString.length();
        int size = Math.max(2*length, 1);
        first = length/4;
        if (limitSize) {
            first = 0;
            size = Math.max(length, 1);
        }
        d = new boolean[size];
        for (int i=0; i<length; i++) {
            if (binaryString.charAt(i) == '1') d[i+first] = true;
        }
    }

    public void addFirst(char c) {
        if (first-1 < 0) doubleArraySize();
        first--;
        d[first] = (c == '1' ? true : false);
        length++;
    }

    public void addLast(char c) {
        if (first+length >= d.length) doubleArraySize();
        d[first+length] = (c == '1' ? true : false);
        length++;
    }

    private void doubleArraySize() {
        boolean[] bigArray = new boolean[(d.length+1) * 2];
        int newFirst = bigArray.length / 4;
        for (int i=0; i<length; i++) {
            bigArray[i + newFirst] = d[i + first];
        }
        first = newFirst;
        d = bigArray;
    }

    public boolean flip(int i) {
        boolean value = (this.d[first+i] ? false : true);
        this.d[first+i] = value;
        return value;
    }

    public void set(int i, char c) {
        boolean value = (c == '1' ? true : false);
        this.d[first+i] = value;
    }

    public char get(int i) {
        return (this.d[first+i] ? '1' : '0');
    }

    @Override
    public int compareTo(Binary o) {
        if (this.length != o.length) return this.length - o.length;
        int len = this.length;
        for (int i=0; i<len; i++) {
            int diff = this.get(i) - o.get(i);
            if (diff != 0) return diff;
        }
        return 0;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (int i=0; i<length; i++) {
            sb.append(d[i+first] ? '1' : '0');
        }
        return sb.toString();
    }

}

/*

class oldWayOfDoingTheSameThing {

    public static void main(String[] args) {
        IO io = new IO();
        try {
            io.println(codeForce(io));
        } finally {
            //System.out.println("CLOSING FINALLY");
            io.close();
        }
    }

    public static long codeForce(IO io) {
        long a = io.nextLong();
        long b = io.nextLong();
        String bin = Long.toBinaryString(a);
        String goal = Long.toBinaryString(b);
        int indexForInitialZero = 0; // placeholder value

        //System.out.println("BIN: " + bin);
        //System.out.println("GOAL: " + goal);

        // We want to start with a binary string that has a single 0
        // If we have too much, fill out extra 0's with 1's
        // Going right->left to increase value as little as possible
        int zerosInBin = countZeros(bin);
        for (int i=bin.length()-1; zerosInBin>1; i--) {
            if (bin.charAt(i) == '0') {
                zerosInBin--;
                StringBuilder newBin = new StringBuilder();
                if (i>0) newBin.append(bin.substring(0,i));
                newBin.append('1');
                if (i<bin.length()-1) newBin.append(bin.substring(i+1, bin.length()));
                bin = newBin.toString();
            }
        }

        // If we have no zeros in starting binary string, turn 111 -> 1011
        if (zerosInBin == 0) {
            String possibleAddition = "";
            if (bin.length() > 1) possibleAddition = bin.substring(1,bin.length());
            if (goal.length() < bin.length()+1) return 0;
            if (goal.length() == bin.length()+1 && !stringIsBelowOrAtGoal(1, goal)) {
                Long parsed = Long.parseLong("10" + possibleAddition, 2);
                if (parsed > b) {
                    //System.out.println("parsed: " + parsed);
                    return 0;
                }
                else {
                    long count = 0;
                    if (goal.contains("0")) count++;
                    if (b != parsed) count++;
                    return count;
                }
            }
            bin = "10" + possibleAddition;
        }
        // Find initial zero
        int i=0;
        for ( ;i<bin.length(); i++) {
            if (bin.charAt(i) == '0') break;
        }
        indexForInitialZero = i;

        // First round may start from middle so do it separately
        long count = 0;
        for (i=indexForInitialZero; i<bin.length(); i++) {
            Long parsed = Long.parseLong(bin, 2);
            if (parsed <= b) count++;
            if (parsed >= b) return count;

            int len = bin.length();
            bin = "";

            for (int j=0; j<=i; j++) {
                bin += '1';
            }
            if (bin.length() < len) {
                bin += '0';
            }
            for (int j=i+2; j<len; j++) {
                bin += '1';
            }
        }

        // All other rounds. specRep represents binary strings
        // from 11110 -> 10111
        int specRep = bin.length()+1;
        boolean doneSomethingHere = false;
        while (specRep <= goal.length() + 1) {
            if (specRep == goal.length()+1) {
                // We possibly counted too many
                // Subtract the ones that went over
                if (!doneSomethingHere) return count;
                while (specRep > goal.length()) specRep--;
                for (i=specRep-1; i>=1; i--) {
                    if (stringIsBelowOrAtGoal(i, goal)) break;
                    count--;
                }
                return count;
            }
            doneSomethingHere = true;
            count += (specRep-1); // bc cant replace first '1' with '0'
            specRep++;
        }

        return count;
    }

    public static boolean stringIsBelowOrAtGoal(int a, String b) {
        // a represents a string that has same length as b
        // with all characters '1' except for a single '0' in index a
        for (int i=1; i<a; i++) {
            if (b.charAt(i) == '0') return false;
        }
        if (b.charAt(a) == '1') return true;
        for (int i=a+1; i<b.length(); i++) {
            if (b.charAt(i) == '0') return false;
        }
        return true;
    }

    public static int countZeros(String a) {
        int count = 0;
        for (int i=0; i<a.length(); i++) {
            if (a.charAt(i) == '0') count++;
        }
        return count;
    }

    static class IO extends PrintWriter {
	private InputStreamReader r;
	private static final int BUFSIZE = 1 << 15;
	private char[] buf;
	private int bufc;
	private int bufi;
	private StringBuilder sb;

	public IO() {
		super(new BufferedOutputStream(System.out));
		r = new InputStreamReader(System.in);

		buf = new char[BUFSIZE];
		bufc = 0;
		bufi = 0;
		sb = new StringBuilder();
	}

	private void fillBuf() throws IOException {
		bufi = 0;
		bufc = 0;
		while(bufc == 0) {
			bufc = r.read(buf, 0, BUFSIZE);
			if(bufc == -1) {
				bufc = 0;
				return;
			}
		}
	}

	private boolean pumpBuf() throws IOException {
		if(bufi == bufc) {
			fillBuf();
		}
		return bufc != 0;
	}

	private boolean isDelimiter(char c) {
		return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f';
	}

	private void eatDelimiters() throws IOException {
		while(true) {
			if(bufi == bufc) {
				fillBuf();
				if(bufc == 0) throw new RuntimeException("IO: Out of input.");
			}

			if(!isDelimiter(buf[bufi])) break;
			++bufi;
		}
	}

	public String next() {
		try {
			sb.setLength(0);

			eatDelimiters();
			int start = bufi;

			while(true) {
				if(bufi == bufc) {
					sb.append(buf, start, bufi - start);
					fillBuf();
					start = 0;
					if(bufc == 0) break;
				}

				if(isDelimiter(buf[bufi])) break;
				++bufi;
			}

			sb.append(buf, start, bufi - start);

			return sb.toString();
		} catch(IOException e) {
			throw new RuntimeException("IO.next: Caught IOException.");
		}
	}

	public int nextInt() {
		try {
			int ret = 0;

			eatDelimiters();

			boolean positive = true;
			if(buf[bufi] == '-') {
				++bufi;
				if(!pumpBuf()) throw new RuntimeException("IO.nextInt: Invalid int.");
				positive = false;
			}

			boolean first = true;
			while(true) {
				if(!pumpBuf()) break;
				if(isDelimiter(buf[bufi])) {
					if(first) throw new RuntimeException("IO.nextInt: Invalid int.");
					break;
				}
				first = false;

				if(buf[bufi] >= '0' && buf[bufi] <= '9') {
					if(ret < -214748364) throw new RuntimeException("IO.nextInt: Invalid int.");
					ret *= 10;
					ret -= (int)(buf[bufi] - '0');
					if(ret > 0) throw new RuntimeException("IO.nextInt: Invalid int.");
				} else {
					throw new RuntimeException("IO.nextInt: Invalid int.");
				}

				++bufi;
			}

			if(positive) {
				if(ret == -2147483648) throw new RuntimeException("IO.nextInt: Invalid int.");
				ret = -ret;
			}

			return ret;
		} catch(IOException e) {
			throw new RuntimeException("IO.nextInt: Caught IOException.");
		}
	}

	public long nextLong() {
		try {
			long ret = 0;

			eatDelimiters();

			boolean positive = true;
			if(buf[bufi] == '-') {
				++bufi;
				if(!pumpBuf()) throw new RuntimeException("IO.nextLong: Invalid long.");
				positive = false;
			}

			boolean first = true;
			while(true) {
				if(!pumpBuf()) break;
				if(isDelimiter(buf[bufi])) {
					if(first) throw new RuntimeException("IO.nextLong: Invalid long.");
					break;
				}
				first = false;

				if(buf[bufi] >= '0' && buf[bufi] <= '9') {
					if(ret < -922337203685477580L) throw new RuntimeException("IO.nextLong: Invalid long.");
					ret *= 10;
					ret -= (long)(buf[bufi] - '0');
					if(ret > 0) throw new RuntimeException("IO.nextLong: Invalid long.");
				} else {
					throw new RuntimeException("IO.nextLong: Invalid long.");
				}

				++bufi;
			}

			if(positive) {
				if(ret == -9223372036854775808L) throw new RuntimeException("IO.nextLong: Invalid long.");
				ret = -ret;
			}

			return ret;
		} catch(IOException e) {
			throw new RuntimeException("IO.nextLong: Caught IOException.");
		}
	}

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

    }
}

/*


import java.util.*;import java.io.*;import java.math.*;
public class Main
{
    public static void process()throws IOException
    {
        int n=ni();
        if(n%2==0)
        {
            pn("white");
            pn("1 2");
        }
        else pn("black");
    }

    static AnotherReader sc;
    static PrintWriter out;
    public static void main(String[]args)throws IOException
    {
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
        if(oj){sc=new AnotherReader();out=new PrintWriter(System.out);}
        else{sc=new AnotherReader(100);out=new PrintWriter("output.txt");}
        int t=1;
        // t=ni();
        while(t-->0) {process();}
        out.flush();out.close();
    }

    static void pn(Object o){out.println(o);}
    static void p(Object o){out.print(o);}
    static void pni(Object o){out.println(o);out.flush();}
    static int ni()throws IOException{return sc.nextInt();}
    static long nl()throws IOException{return sc.nextLong();}
    static double nd()throws IOException{return sc.nextDouble();}
    static String nln()throws IOException{return sc.nextLine();}
    static int[] nai(int N)throws IOException{int[]A=new int[N];for(int i=0;i!=N;i++){A[i]=ni();}return A;}
    static long[] nal(int N)throws IOException{long[]A=new long[N];for(int i=0;i!=N;i++){A[i]=nl();}return A;}
    static long gcd(long a, long b)throws IOException{return (b==0)?a:gcd(b,a%b);}
    static int gcd(int a, int b)throws IOException{return (b==0)?a:gcd(b,a%b);}
    static int bit(long n)throws IOException{return (n==0)?0:(1+bit(n&(n-1)));}

/////////////////////////////////////////////////////////////////////////////////////////////////////////

    static class AnotherReader{BufferedReader br; StringTokenizer st;
    AnotherReader()throws FileNotFoundException{
    br=new BufferedReader(new InputStreamReader(System.in));}
    AnotherReader(int a)throws FileNotFoundException{
    br = new BufferedReader(new FileReader("input.txt"));}
    String next()throws IOException{
    while (st == null || !st.hasMoreElements()) {try{
    st = new StringTokenizer(br.readLine());}
    catch (IOException  e){ e.printStackTrace(); }}
    return st.nextToken(); } int nextInt() throws IOException{
    return Integer.parseInt(next());}
    long nextLong() throws IOException
    {return Long.parseLong(next());}
    double nextDouble()throws IOException { return Double.parseDouble(next()); }
    String nextLine() throws IOException{ String str = ""; try{
    str = br.readLine();} catch (IOException e){
    e.printStackTrace();} return str;}}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
}v


package all1500;

import java.util.Scanner;

public class Asdf
{
	static Scanner sc = new Scanner(System.in);
	static int n;

	public static void main(String[] args)
	{
		n = sc.nextInt();
		int m = n%2;
		if(m < 0)m+=2;

		if(m == 1)
		{
			System.out.println("black");
		}
		else
		{
			System.out.println("white");
			System.out.println("1 2");
		}
	}

}


public class ComProgSetUp {

	public static int getNumber(String fN) {
		int res=0;
		int n = fN.length();
		for(int i=1; i<n-1; i++)
			if(fN.charAt(i)=='x')
				if(fN.charAt(i-1) == fN.charAt(i) && fN.charAt(i+1) == fN.charAt(i))
					res++;
		return res;
	}

	public static void main(String[] args) {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n=0;
		String T = br.readLine();
		if(T != null) n = Integer.parseInt(T);
		String fileName = br.readLine();
		System.out.println(getNumber(fileName));
	}
}


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

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author masterbios
 */
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);
        CAnadiAndDomino solver = new CAnadiAndDomino();
        solver.solve(1, in, out);
        out.close();
    }

    static class CAnadiAndDomino {
        int ans = 0;
        int x = new int[1000];
        int sparse;
        int u;
        int v;
        int edgecount = 0;
        int vertices = 0;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            vertices = in.nextInt();
            edgecount = in.nextInt();
            sparse = new int[8][8];
            u = new int[edgecount];
            v = new int[edgecount];
            for (int i = 0; i < edgecount; i++) {
                u[i] = in.nextInt();
                v[i] = in.nextInt();
            }
            getanswer(1);
            out.println(ans);
        }

        private void getanswer(int i) {
            if (i == vertices + 1) {
                ans = Math.max(ans, check());
                return;
            }
            for (int k = 1; k <= 6; k++) {
                x[i] = k;
                getanswer(i + 1);
            }
        }

        private int check() {
            int now = 0;
            for (int i = 1; i <= 6; i++) Arrays.fill(sparse[i], 0);
            for (int i = 0; i < edgecount; i++) {
                int min = Math.min(x[u[i]], x[v[i]]);
                int max = Math.max(x[u[i]], x[v[i]]);
                sparse[min][max] = 1;
            }
            for (int i = 1; i <= 6; i++) {
                for (int j = i; j <= 6; j++) {
                    now += sparse[i][j];
                }
            }
            return now;
        }

    }

    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.hasMoreElements()) {
                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.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {
    static boolean vis[], taken[][];
    static int deg[];
    static ArrayList<Integer> adjList[];
    static int cand;

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner();
        PrintWriter out = new PrintWriter(System.out);
        int n = sc.nextInt(), m = sc.nextInt();
        if (n != 7) out.println(m);
        else {
            adjList = new ArrayList[n];
            for (int i = 0; i < n; i++)
                adjList[i] = new ArrayList<>();
            while (m-- > 0) {
                int a = sc.nextInt() - 1, b = sc.nextInt() - 1;
                adjList[a].add(b);
                adjList[b].add(a);
            }
            deg = new int[n];
            int ans = 0;
            for (int i = 0; i < n - 1; i++)
                deg[i] = i;
            for (int d = 0; d < n - 1; d++) {
                deg[n - 1] = d;
                vis = new boolean[n];
                taken = new boolean[n][n];
                cand = 0;
                for (int i = 0; i < n; i++)
                    if (!vis[i]) {
                        dfs(i);
                    }
                ans = Math.max(ans, cand);
            }
            out.println(ans);
        }
        out.flush();
    }

    static void dfs(int u) {
        vis[u] = true;
        for (int v : adjList[u]) {
            if (!taken[deg[u]][deg[v]]) {
                taken[deg[u]][deg[v]] = true;
                taken[deg[v]][deg[u]] = true;
                cand++;
            }
            if (!vis[v]) dfs(v);
        }
    }

    static class Scanner {
        BufferedReader br;
        StringTokenizer st;

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

        }

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

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

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

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

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

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

    }

}


import java.util.*;

public class bucky{

public static void main (String args[]) {

Scanner input=new Scanner(System.in);

HashMap<String, Integer> map= new HashMap<String, Integer>();
HashMap<String, String> map2= new HashMap<String, String>();

		int n=input.nextInt();

		String nums[]=new String[100001];

		nums[1]="1";
		nums[2]="2";

		for(int i=3;i<=10;i++){

		String intrare=nums[i-1]+"1";

	//	System.out.println(intrare);

		nums[i]=functie(intrare);

	//	System.out.println(i+"  "+nums[i]);

		}

		for(int i=0;i<nums[n].length();i++)

		System.out.print(nums[n].charAt(i)+" ");

		}

		public static String functie(String str){
		int x=1;
		while(x==1){
		x=0;

		for(int i=0;i<str.length()-1;i++)

		if(str.charAt(i)==str.charAt(i+1)) {

		x=1;

		String a=str.substring(i,i+2);

		int b=Integer.parseInt(str.substring(i,i+1))+1;

		String inlocuit=String.valueOf(b);

		String altul=str.replaceAll(a,inlocuit);
		str=altul;
	//	System.out.println("altul="+altul);

		}

		}

		return str;

		}

		}


import java.io.PrintStream;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.SortedMap;
import java.util.Map;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.TreeMap;
import java.util.InputMismatchException;
import java.util.Set;
import java.util.NavigableMap;
import java.io.Reader;
import java.io.InputStream;

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

class TaskE {

    static int[] g;
    static int MAXN = 1000;

    static {
        g = new int[MAXN];
        for (int i = 3; i < g.length; i++) {
            int g1 = g[i / 3];
            int g2 = g[i - i / 3];
            for (int j = 0; j < 3; j++) {
                if (g1 == j || g2 == j) {
                    continue;
                }
                g[i] = j;
                break;
            }
            System.out.print(g[i]);
        }
        System.out.println();
        for (int i = 3; i < g.length; i++) {
            System.out.print(i % 10);
        }
    }

    static final int MOD = 1000000007;

    public void solve(int testNumber, FastScanner in, FastPrinter out) {
        int n = in.nextInt();
        int p = in.nextInt();
        NavigableMap<Integer, Integer> g = new TreeMap<Integer, Integer>();
        g.put(1, 0);
        g.put(3, 1);
        for (int d = 3; d < p - 1; ) {
            int a = d / 3;
            int b = d - d / 3;
            Integer na = g.higherKey(a);
            Integer nb = g.higherKey(b);
            if (na == null || nb == null) {
                throw new AssertionError();
            }
            long z1 = na * 3L;
            long z2 = 3L * nb / 2;
            while (z2 - z2 / 3 >= nb) {
                z2--;
            }
            while (z2 - z2 / 3 < nb) {
                ++z2;
            }
            long z = Math.min(z1, z2);
            if (z > p - 1) {
                break;
            }
            int zi = (int) z;
            int ga = g.get(g.floorKey(zi / 3));
            int gb = g.get(g.floorKey(zi - zi / 3));
            int ng = -1;
            for (int j = 0; j < 3; j++) {
                if (j == ga || j == gb) {
                    continue;
                }
                ng = j;
                break;
            }
            g.put(zi, ng);
            d = zi;
        }
        long[] count = new long[3];
        for (int i : g.keySet()) {
            Integer ni = g.higherKey(i);
            if (ni == null) {
                ni = p;
            }
            int first = p - i;
            int second = p - ni;
            count[g.get(i)] += s(second + 1, first + 1);
        }
        for (int i = 0; i < 3; i++) {
            count[i] %= MOD;
        }
        int[][] dp = new int[n + 1][4];
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int x = 0; x < 3; x++) {
                for (int y = 0; y < 4; y++) {
                    dp[i][x ^ y] = (int) ((dp[i][x ^ y] + (long) dp[i - 1][y] * count[x]) % MOD);
                }
            }
        }
        long ans = 0L + dp[n][1] + dp[n][2] + dp[n][3];
        out.println(ans % MOD);
    }

    static long s(int a, int b) {
        if (a >= b) {
            return 0;
        }
        --b;
        --a;
        long ret = ss(b) - ss(a);
        return ret;
    }

    static long ss(int n) {
        return (long) n * (n + 1) / 2;
    }
}

class FastScanner extends BufferedReader {

    boolean isEOF;

    public FastScanner(InputStream is) {
        super(new InputStreamReader(is));
    }

    public int read() {
        try {
            int ret = super.read();
            if (isEOF && ret < 0) {
                throw new InputMismatchException();
            }
            isEOF = ret == -1;
            return ret;
        } catch (IOException e) {
            throw new InputMismatchException();
        }
    }

    static boolean isWhiteSpace(int c) {
        return c >= -1 && c <= 32;
    }

    public int nextInt() {
        int c = read();
        while (isWhiteSpace(c)) {
            c = read();
        }
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int ret = 0;
        while (!isWhiteSpace(c)) {
            if (c < '0' || c > '9') {
                throw new NumberFormatException("digit expected " + (char) c
                        + " found");
            }
            ret = ret * 10 + c - '0';
            c = read();
        }
        return ret * sgn;
    }

    }

class FastPrinter extends PrintWriter {

    public FastPrinter(OutputStream out) {
        super(out);
    }

    public FastPrinter(Writer out) {
        super(out);
    }

}


import java.util.Map;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.InputMismatchException;
import java.util.TreeMap;
import java.util.Set;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.util.NavigableMap;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.SortedMap;
import java.io.InputStream;

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

class TaskE {

    static final int MOD = 1000000007;

    public void solve(int testNumber, FastScanner in, FastPrinter out) {
        int n = in.nextInt();
        int p = in.nextInt();
        NavigableMap<Integer, Integer> g = new TreeMap<Integer, Integer>();
        g.put(1, 0);
        g.put(3, 1);
        for (int d = 3; d < p - 1; ) {
            int a = d / 3;
            int b = d - d / 3;
            Integer na = g.higherKey(a);
            Integer nb = g.higherKey(b);
            if (na == null || nb == null) {
                throw new AssertionError();
            }
            long z1 = na * 3L;
            long z2 = 3L * nb / 2;
            while (z2 - z2 / 3 >= nb) {
                z2--;
            }
            while (z2 - z2 / 3 < nb) {
                ++z2;
            }
            long z = Math.min(z1, z2);
            if (z > p - 1) {
                break;
            }
            int zi = (int) z;
            int ga = g.get(g.floorKey(zi / 3));
            int gb = g.get(g.floorKey(zi - zi / 3));
            int ng = -1;
            for (int j = 0; j < 3; j++) {
                if (j == ga || j == gb) {
                    continue;
                }
                ng = j;
                break;
            }
            g.put(zi, ng);
            d = zi;
        }
        long[] count = new long[3];
        for (int i : g.keySet()) {
            Integer ni = g.higherKey(i);
            if (ni == null) {
                ni = p;
            }
            int first = p - i;
            int second = p - ni;
            count[g.get(i)] += s(second + 1, first + 1);
        }
        for (int i = 0; i < 3; i++) {
            count[i] %= MOD;
        }
        int[][] dp = new int[n + 1][4];
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int x = 0; x < 3; x++) {
                for (int y = 0; y < 4; y++) {
                    dp[i][x ^ y] = (int) ((dp[i][x ^ y] + (long) dp[i - 1][y] * count[x]) % MOD);
                }
            }
        }
        long ans = 0L + dp[n][1] + dp[n][2] + dp[n][3];
        out.println(ans % MOD);
    }

    static long s(int a, int b) {
        if (a >= b) {
            return 0;
        }
        --b;
        --a;
        long ret = ss(b) - ss(a);
        return ret;
    }

    static long ss(int n) {
        return (long) n * (n + 1) / 2;
    }
}

class FastScanner extends BufferedReader {

    boolean isEOF;

    public FastScanner(InputStream is) {
        super(new InputStreamReader(is));
    }

    public int read() {
        try {
            int ret = super.read();
            if (isEOF && ret < 0) {
                throw new InputMismatchException();
            }
            isEOF = ret == -1;
            return ret;
        } catch (IOException e) {
            throw new InputMismatchException();
        }
    }

    static boolean isWhiteSpace(int c) {
        return c >= -1 && c <= 32;
    }

    public int nextInt() {
        int c = read();
        while (isWhiteSpace(c)) {
            c = read();
        }
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int ret = 0;
        while (!isWhiteSpace(c)) {
            if (c < '0' || c > '9') {
                throw new NumberFormatException("digit expected " + (char) c
                        + " found");
            }
            ret = ret * 10 + c - '0';
            c = read();
        }
        return ret * sgn;
    }

    }

class FastPrinter extends PrintWriter {

    public FastPrinter(OutputStream out) {
        super(out);
    }

    public FastPrinter(Writer out) {
        super(out);
    }

}


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

public class TaskC {

    private static long MOD = 1_000_000_000+7;

    public static void main(String[] arg)  {
        final FastScanner in = new FastScanner(System.in);
        final PrintWriter out = new PrintWriter(System.out);
        final int n = in.nextInt();
        final int x = in.nextInt();
        final int pos = in.nextInt();
        out.println(solution(pos, n, x));
        out.close();
        in.close();
    }

    private static long solution(int pos,
                                   int len,
                                   int e){
        String path = bs(pos, len, e);
        //System.out.println(path);
        long permut = mod_fact(len-1-path.length());
        long traverse = traverse(e, 1, len, path.toCharArray(),0);
        return (permut*traverse)%MOD;
    }

    private static String bs(int pos, int len,
                           int element){
        int left = 0;
        int right = len;
        int deep = 1;
        StringBuilder path = new StringBuilder();
        while(left<right) {
            int middle = (left + right)/2;
            if(middle==pos){
                return path.toString();
            }
            deep++;

            if (middle < pos) {
                path.append('r');
                left = middle + 1;
            } else {
                path.append('l');
                right = middle;
            }
        }
        return path.toString();
    }

    private static long traverse(final int x,
                                 final int min,
                                 final int n,
                                 final char []s,
                                 final int p){
        if(p==s.length){
            return 1;
        }
        long result = 1;
        if(s[p]=='l'){
            for(int i=x+1;i<n;i++){
              result+=traverse(x, min, i, s, p+1)%MOD;
              result%=MOD;
            }
        }
        if(s[p]=='r'){
            for(int i=min;i<x;i++){
                result+=traverse(x, i, n, s, p+1)%MOD;
                result%=MOD;
            }
        }
        return result%MOD;
    }

    private  static int cnt(){
        int n = 9;
        int result = 0;
        for(int i=9;i>=1;i--){
                result+=(i-1);
        }
        return result;
    }

    private static long mod_fact(int n){
        long result =1;
        for(int i=2;i<=n;i++){
            result*=i;
            result%=MOD;
        }
        return result;
    }

    private static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        FastScanner(InputStream stream) {
            try {
                br = new BufferedReader(new InputStreamReader(stream));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

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

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

        int[] readIntArr(int n) {
            int[] result = new int[n];
            for (int i = 0; i < n; i++) {
                result[i] = Integer.parseInt(next());
            }
            return result;
        }

        void close() {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

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

    }
}


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

import Combinatorics.Pair;

public class C {

	public static void main(String[] args) {
		FastScanner sc = new FastScanner();
		int n = sc.nextInt();
		int x = sc.nextInt();
		int p = sc.nextInt();
		int[] arr = new int[n];
		for(int i = 0; i <= p; i++) {
			arr[i] = x;
		}
		for(int i = p+1; i < n; i++) {
			arr[i] = x+1;
		}
		boolean[] mark = new boolean[n];
		int a = 0, b = n;
		while(a < b) {
			int c = (a+b)/2;
			mark[c] = true;
			if(arr[c] <= x) a = c+1;
			else b = c;
		}
		int leq = 0, high = 0;
		for(int i = 0; i < n; i++) {
			if(mark[i] && arr[i] == x) leq++;
			if(mark[i] && arr[i] > x) high++;
		}
		long res = choose(x-1, leq-1) * fac(leq-1) % mod;
		res = res * choose(n-x, high) % mod * fac(high) % mod;
		System.out.println(res * fac(n - leq - high) % mod);
	}
	static long mod = 1000000007;
	static int N = 1001;
	static long[] fac = new long[N+1];
	static long[] invfac = new long[N+1];
	static long fac(int n){
		if(n == 0) return fac[0] = 1;
		else if(fac[n] > 0) return fac[n];
		else return fac[n] = n * fac(n-1) % mod;
	}
	static long invfac(int n){
		if(invfac[n] > 0) return invfac[n];
		else return invfac[n] = inv(fac[n]);
	}
	static long choose(int n, int k){
		if(k > n || k < 0) return 0;
		return fac(n) * invfac(k) % mod * invfac(n-k) % mod;
	}
	static long inv(long a){
		return (gcdex(a, mod).r + mod) % mod;
	}
	static Pair gcdex(long a, long b){
		if(b > a) return gcdex(b, a).invert();
		else if(b == 0) return new Pair(1, 0);
		else{
			Pair p = gcdex(b, a % b);
			return new Pair(p.s, p.r - p.s*(a/b));
		}
	}
	static class Pair{
		long r, s;
		public Pair(long r, long s){
			this.r = r; this.s = s;
		}
		public Pair invert(){
			return new Pair(s, r);
		}
		public String toString() {
			return r+" "+s;
		}
	}

	static class FastScanner {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public FastScanner() {
            reader = new BufferedReader(new InputStreamReader(System.in), 32768);
            tokenizer = null;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
        	return Long.parseLong(next());
        }
        public double nextDouble() {
        	return Double.parseDouble(next());
        }
        public String nextLine() {
        	try {
        		return reader.readLine();
        	} catch(IOException e) {
        		throw new RuntimeException(e);
        	}
        }
    }

}


import java.io.InputStreamReader;
import java.util.Scanner;

public class Main {
    static long MOD = 1000000007;

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int x = sc.nextInt();
        int pos = sc.nextInt();
        long ans = 1;
        int left= 0, right = n, mid, low = x-1, high = n-x;
        while (left < right) {
            mid = (left + right)/2;
            if (mid < pos) {

                if (low == 0) {
                    System.out.println(0);
                    return;
                } else {
                    ans = (ans*low)%MOD;
                    low--;
                }
                left = mid+1;
            } else if (mid == pos) {
                left = mid+1;
            } else {
                if (high == 0) {
                    System.out.println(0);
                    return;
                } else {
                    ans = (ans*high)%MOD;
                    high--;
                }
                right = mid;
            }
        }
        System.out.println(ans);

        for (int i = 0; i < low+high; i++)
            ans = (ans*(low+high-i)) % MOD;
        System.out.println(ans);

    }
}


package CodeForces;

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

public class C
{
	static long facts[],factInvs[],mod=(long)1e9+7;

	public static void main(String[] args)throws IOException
	{
		FastReader f=new FastReader();
		StringBuffer sb = new StringBuffer();
		precomp();

		int test=1;
		while(test-->0)
		{
			int n=f.nextInt();
			int x=f.nextInt();
			int pos=f.nextInt();

			int small=0;int big=0;
			int l=0;
			int r=n;
			while(l<r)
			{
				int mid=(l+r)/2;
				if(mid>pos)
					big++;
				if(mid<pos)
					small++;

				if(mid<=pos)
					l=mid+1;
				else
					r=mid;
			}
			long ans=(getNcR(x-1,small)
					    *getNcR(n-x,big)%mod
					    *facts[(n-small-big-1)]%mod
					    *facts[small]%mod
					    *facts[big]%mod;)

			System.out.println(ans);
		}

    }

	static void precomp() {
		facts = new long[1000000];
		factInvs = new long[1000000];
		factInvs[0] = facts[0] = 1;

		for (int i = 1; i < facts.length; i++)
			facts[i] = mul(facts[i - 1], i);

		factInvs[facts.length - 1] = modInv(facts[facts.length - 1]);

		for (int i = facts.length - 2; i >= 0; i--)
			factInvs[i] = mul(factInvs[i + 1], i + 1);
	}

	static long getNcR(int n, int k) {
		return mul(facts[n], mul(factInvs[k], factInvs[n - k]));
	}

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

	static long modInv(long x) {
		return exp(x, mod - 2);
	}

	static long exp(long base, long e) {
		if (e == 0)
			return 1;
		long half = exp(base, e / 2);
		if (e % 2 == 0)
			return mul(half, half);
		else
			return mul(half, mul(half, base));
	}

	static class FastReader
	{
	    BufferedReader br;
	    StringTokenizer st;

	    public FastReader() {
	    	br = new BufferedReader(new
	                 InputStreamReader(System.in));
	    }
	    String next() {
	        while (st == null || !st.hasMoreElements()) {
	            try{
	                st = new StringTokenizer(br.readLine());
	            }
	            catch (IOException  e) {
	                e.printStackTrace();
	            }
	        }
	        return st.nextToken();
	    }
	    int nextInt() {
	        return Integer.parseInt(next());
	    }
	    long nextLong() {
	        return Long.parseLong(next());
	    }
	    double nextDouble() {
	        return Double.parseDouble(next());
	    }
	    String nextLine() {
	        String str = "";
	        try{
	            str = br.readLine();
	        }
	        catch (IOException e) {
	            e.printStackTrace();
	        }
	        return str;
	    }
	}

}


import java.util.*;
public class susbus{
   public static void main(String[] args){
      Scanner sc = new Scanner(System.in);
      int x = sc.nextInt();
      int y = sc.nextInt();
      int a = sc.nextInt();
      int b = sc.nextInt();
      int s = b/gcd(x,y);
      int t = (a-1)/gcd(x,y);
      System.out.println(s-t);
   }
   public static int gcd(int x, int y){
      int result=0;
      int k = Math.sqrt(Math.min(x,y));
      for (int i=1;i<=k;i++){
         if(x%i==0 && y%i==0){
            result=i;
         }
      }
      return result;
   }
}


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

public class Main {

	static int MOD = 1000 * 1000 * 1000 + 7;

	public static void shuffleArray(int[] arr) {
		int n = arr.length;
		Random rnd = new Random();
		for (int i = 0; i < n; ++i) {
			int tmp = arr[i];
			int randomPos = i + rnd.nextInt(n - i);
			arr[i] = arr[randomPos];
			arr[randomPos] = tmp;
		}
	}

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

	private static void solve(InputReader in, PrintWriter out) {

		int n = in.nextInt();
		long k = in.nextLong();
		long[] fib = new long[51];
		fib[0] = 0;
		fib[1] = 1;
		fib[2] = 2;
		for (int i = 3; i <= 50; i++) {
			fib[i] = fib[i - 1] + fib[i - 2];
		}

		int pos = 1;
		int i = n;
		while (pos <= n) {
			if (pos == n && k == 1) {
				out.print(pos);
				break;
			}

			if (k <= fib[i - 1]) {
				out.print(pos + " ");
				pos++;
				i -= 1;
			} else {
				k -= fib[i - 1];
				out.print((pos + 1) + " " + pos);
				pos += 2;
				i -= 2;
			}
		}

	}

	/*
	 *
	 */
	// --------------------------------------------------------
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

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

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

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

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

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

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

			return str;
		}
	}

}


import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;

/**
 * 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;
        MyScanner in = new MyScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }
}

class TaskD {
    int MOD = (int) (1e9+7);
    public void solve(int testNumber, MyScanner in, PrintWriter out) {
        int h = in.nextInt(), w = in.nextInt();
        long res = solve(h,w);
        out.println(res);
    }

    private long solve(int h, int w) {
        h++; w++;
        long[][] num = new long[2][2];
        for (int i = 0; i < h; i++) for (int j = 0; j < w; j++)num[i%2][j%2]++;
        long numInt = 0;
        for (int x0 = 0; x0 < 2; x0++) for (int y0 = 0; y0 < 2; y0++) for (int x1 = 0; x1 < 2; x1++)
            for (int y1 = 0; y1 < 2; y1++) for (int x2 = 0; x2 < 2; x2++) for (int y2 = 0; y2 < 2; y2++){
                int dx1 = (x1-x0)&1, dy1 = (y1-y0)&1;
                int dx2 = (x2-x0)&1, dy2 = (y2-y0)&1;
                if((dx1*dy2-dx2*dy1&1)==0){
                    numInt = (numInt + num[x0][y0] * num[x1][y1] % MOD * num[x2][y2]) % MOD;
                }
            }

        long zero = 0;
        long S = h * w;
        zero += S;
        zero += S*(S-1)*3; zero %= MOD;

        zero += h*(h-1)%MOD*(h-2)*w;
        zero += w*(w-1)%MOD*(w-2)*h;
        zero %= MOD;

        for(int x=1;x<h;x++)for(int y=1;y<w;y++){
            int g = MathUtils.gcd(x,y);
            zero = (zero + (g-1) * (h-x) * (w-y) * 12) % MOD;
        }
        return (numInt - zero + MOD)  % MOD;
    }
}

class MyScanner {
    private final InputStream in;
    public MyScanner(InputStream in){
        this.in = in;
    }

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

    }

class MathUtils {

    public static int gcd(int x,int y){
        while (y != 0) {
            x %= y;
            if (x == 0) return y;
            y %= x;
        }
        return x;
    }

    }


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

public class Solution implements Runnable {

	BufferedReader in;
	PrintWriter out;
	StringTokenizer st;

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

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

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

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

	long modd = 1000000007;

	long gcd(long a, long b) {
		while (b != 0) {
			long t = a % b;
			a = b;
			b = t;
		}
		return a;
	}

	long f(int a, int b) {
		long res = 0;
		boolean evens = a * b % 2 == 0;
		if (evens) {
			res = 2 * a + 2 * b;
		}
		long all = (a - 1) * (b - 1);
		long odd = a / 2 * (b / 2);
		if (evens) {
			res = (res + 4 * (all - odd)) % modd;
		} else {
			res = (res + 4 * odd) % modd;
		}
		long aeven = 0;
		if (a % 2 == 0) aeven = b + 1; else {
			aeven = (b + 2) / 2;
		}
		long aodd = b + 1 - aeven;
		long beven = 0;
		if (b % 2 == 0) beven = a + 1; else {
			beven = (a + 2) / 2;
		}
		long bodd = a + 1 - beven;
		long tmp = aeven * beven % modd + aodd * bodd % modd;
		if (evens) tmp = (tmp + modd - 2) % modd;
		tmp = (tmp + modd - gcd(a, b) - 1) % modd;
		return (res + 2 * tmp) % modd;
	}

	int ans(int w, int h) {
		long ans = 0;
		if (w < h) { int t = w; w = h; h = t; }
		for (int i = 1; i <= h; i++) {
			for (int j = i + 1; j <= h; j++) {
				long t = f(i, j);
				ans = (ans + t * (w - i + 1) * (h - j + 1)) % modd;
//				ans = (ans + t * (h - i + 1) * (w - j + 1)) % modd;
			}
		}
		for (int i = 1; i <= h; i++) {
			long t = f(i, i);
			ans = (ans + t * (w - i + 1) % modd * (h - i + 1)) % modd;
		}
		for (int i = h + 1; i <= w; i++) {
			for (int j = 1; j <= h; j++) {
				long t = f(i, j);
				ans = (ans + t * (w - i + 1) % modd * (h - j + 1)) % modd;
			}
		}
		return (int)(ans * 6 % modd);
	}

	void solve() throws Exception {
		int w = nextInt(), h = nextInt();
		out.println(ans(w, h));
	}

	public void run() {
		try {
			Locale.setDefault(Locale.UK);
			in = new BufferedReader(new InputStreamReader(System.in));
			// in = new BufferedReader(new FileReader("input.txt"));
			out = new PrintWriter(System.out);
			// out = new PrintWriter("output.txt");
			solve();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		} finally {
			out.close();
		}
	}

	public static void main(String[] args) {
		// new Thread(null, new Solution(), "1", 1 << 28).start();
		(new Solution()).run();
	}

}


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

public class Solution implements Runnable {

	BufferedReader in;
	PrintWriter out;
	StringTokenizer st;

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

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

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

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

	long modd = 1000000007;

	long f(int a, int b) {
		long res = 0;
		boolean evens = a * b % 2 == 0;
		if (evens) {
			res = 2 * a + 2 * b;
		}
		long all = (a - 1) * (b - 1);
		long odd = a / 2 * (b / 2);
		if (evens) {
			res = (res + 4 * (all - odd)) % modd;
		} else {
			res = (res + 4 * odd) % modd;
		}
		long aeven = 0;
		if (a % 2 == 0) aeven = b + 1; else {
			aeven = (b + 2) / 2;
		}
		long aodd = b + 1 - aeven;
		long beven = 0;
		if (b % 2 == 0) beven = a + 1; else {
			beven = (a + 2) / 2;
		}
		long bodd = a + 1 - beven;
		long tmp = aeven * beven % modd + aodd * bodd % modd;
		if (evens) tmp = (tmp + modd - 2) % modd;
		tmp = (tmp + modd - BigInteger.valueOf(a).gcd(BigInteger.valueOf(b)).longValue() - 1) % modd;
		return (res + 2 * tmp) % modd;
	}

	void solve() throws Exception {
		int w = nextInt(), h = nextInt();
		long ans = 0;
		for (int i = 1; i <= w; i++) {
			for (int j = 1; j <= h; j++) {
				long t = f(i, j);
				ans = (ans + t * (w - i + 1) % modd * (h - j + 1)) % modd;
			}
		}
		out.println(ans * 6 % modd);
	}

	public void run() {
		try {
			Locale.setDefault(Locale.UK);
			in = new BufferedReader(new InputStreamReader(System.in));
			// in = new BufferedReader(new FileReader("input.txt"));
			out = new PrintWriter(System.out);
			// out = new PrintWriter("output.txt");
			solve();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		} finally {
			out.close();
		}
	}

	public static void main(String[] args) {
		// new Thread(null, new Solution(), "1", 1 << 28).start();
		(new Solution()).run();
	}

}


import java.util.Scanner;

public class G {
	static final long mod = 1000000007;

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		long X = sc.nextInt();
		long Y = sc.nextInt();
		long add = 0, sub =0;

		long combs = (X+1)*(Y+1);
		long oo = ((X+1)>>1) * ((Y+1)>>1);
		long oe = ((X+1)>>1) * ((Y+2)>>1);
		long eo = ((X+2)>>1) * ((Y+1)>>1);
		long ee = ((X+2)>>1) * ((Y+2)>>1);

		//two
		add+=(ee)*(ee-1)*(combs-ee);
		add+=(eo)*(eo-1)*(combs-eo);
		add+=(oe)*(oe-1)*(combs-oe);
		add+=(oo)*(oo-1)*(combs-oo);

		add*=3;
		add%=mod;

		//three
		add+=(ee)*(ee-1)*(ee-2);
		add+=(eo)*(eo-1)*(eo-2);
		add+=(oe)*(oe-1)*(oe-2);
		add+=(oo)*(oo-1)*(oo-2);

		add%=mod;

		for (int x = (int)-X; x <= X; x++) {
			for (int y = 0; y <= Y; y++) {
				if(x<=0 && y == 0) continue;
				long ways = GCD(Math.abs(y), Math.abs(x)) + 1;
				long pick = (X - Math.abs(x) + 1) * (Y - y + 1);
				long temp = (pick * (6*(ways-2))) % mod;
				if(temp>0){
					sub+=temp%mod;
				}
			}

		}
	//	System.out.println(add+" "+sub);
		System.out.println((((add-sub) % mod)+mod)%mod);
	}

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


import java.util.Scanner;

public class G {
	static final long mod = 1000000007;
	static Long[][] memo = new Long[4005][4005];
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		long X = sc.nextInt();
		long Y = sc.nextInt();
		long add = 0, sub =0;

		long combs = (X+1)*(Y+1);
		long oo = ((X+1)>>1) * ((Y+1)>>1);
		long oe = ((X+1)>>1) * ((Y+2)>>1);
		long eo = ((X+2)>>1) * ((Y+1)>>1);
		long ee = ((X+2)>>1) * ((Y+2)>>1);

		//two
		add+=trip(ee,ee-1,combs-ee);
		add+=trip(eo,eo-1,combs-eo);
		add+=trip(oe,oe-1,combs-oe);
		add+=trip(oo,oo-1,combs-oo);
		add*=3;
		add%=mod;

		//three
		add+=trip(ee,ee-1,ee-2);
		add+=trip(eo,eo-1,eo-2);
		add+=trip(oe,oe-1,oe-2);
		add+=trip(oo,oo-1,oo-2);

		add%=mod;

		for (int x = (int)-X; x <= X; x++) {
			for (int y = 0; y <= Y; y++) {
				if(x<=0 && y == 0) continue;
				long ways = GCD(Math.abs(y), Math.abs(x)) + 1;
				long pick = (X - Math.abs(x) + 1) * (Y - y + 1);
				long temp = (pick * (6*(ways-2))) % mod;
				if(temp>0){
					sub+=temp;
					sub%=mod;
				}
			}

		}
	//	System.out.println(add+" "+sub);
		System.out.println((((add-sub) % mod)+mod)%mod);
	}

	private static long trip(long A, long B, long C) {
		return (((A*B)%mod)*C)%mod;
	}

	private static Long GCD(int a, int b) {
		if(memo[a][b]!=null)return memo[a][b];
		if (b == 0)	return memo[a][b]=(long)a;
		return memo[a][b]=GCD(b, a % b);
	}
}


import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.math.BigInteger;
import java.io.InputStream;

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

class TaskD {
	private static final int modulo = 1000000007;
	private int[] calc(int a, int b) {
		return new int[] {1 + a / 2 + b / 2, (a + 1) / 2 + (b + 1) / 2};
	}
	public void solve(int testNumber, InputReader in, OutputWriter out) {
		int w = in.readInt();
		int h = in.readInt();
		long ans = 0;
		for (int i = 0; i <= w; i ++)
			for (int j = 0; j <= h; j ++) {
				int[] cx = calc(i, w - i);
				int[] cy = calc(j, h - j);
				for (int s = 0; s < 16; s ++) {
					int x1 = s & 1;
					int y1 = s >> 1 & 1;
					int x2 = s >> 2 & 1;
					int y2 = s >> 3 & 1;
					if ((x1 * y2 - x2 * y1) % 2 == 0) {
						ans = (ans + (long)cx[x1] * cy[y1] % modulo * cx[x2] % modulo * cy[y2]) % modulo;
					}
				}
			}
		ans = (ans - (w + 1) * (h + 1)) % modulo;
		ans = (ans - (long)(w + 1) * (h + 1) * ((w + 1) * (h + 1) - 1) * 3) % modulo;
		ans = (ans - (long)(w + 1) * (h + 1) * h * (h - 1)) % modulo;
		ans = (ans - (long)(h + 1) * (w + 1) * w * (w - 1)) % modulo;
		for (int i = 1; i <= w; i ++)
			for (int j = 1; j <= h; j ++) {
				int t = NumberTheory.gcd(i, j) - 1;
				ans = (ans - (long)(w - i + 1) * (h - j + 1) % modulo * t * 12) % modulo;
			}
		ans = (ans + modulo) % modulo;
		out.printLine(ans);
	}
}

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

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

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

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

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

class OutputWriter {
	private final PrintWriter writer;

	public OutputWriter(OutputStream outputStream) {
		writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
	}

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

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

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

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

class NumberTheory {
	private NumberTheory() {
	}

	public static int gcd(int m, int n) {
		if (m == 0) return n;
		while (n > 0) {
			int r = m % n;
			m = n;
			n = r;
		}
		return m;
	}

	}


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

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

class TaskD {
    public static final int MOD = 1000000007;
    private int N, M;
	public void solve(int testNumber, StreamInputReader in, PrintWriter out) {
        M = in.readInt();
        N = in.readInt();
        long ans = 0;
        for(int px0 = 0; px0 < 2; px0++)
        for(int py0 = 0; py0 < 2; py0++)
        for(int px1 = 0; px1 < 2; px1++)
        for(int py1 = 0; py1 < 2; py1++)
        for(int px2 = 0; px2 < 2; px2++)
        for(int py2 = 0; py2 < 2; py2++)
           if((px0 * (py1 - py2 + 2) + py0 * (px2 - px1 + 2) + px1 * py2 - px2 * py1 + 2) % 2 == 0) {
               long crt = 1;
               crt *= px(px0);
               crt *= px(px1);
               crt *= px(px2);
               crt %= MOD;
               crt *= py(py0);
               crt *= py(py1);
               crt *= py(py2);
               ans = (ans + crt) % MOD;
           }

        int[][] gcd = new int[M + 1][N + 1];
        for(int i = 0; i <= M; i++)
            for(int j = 0; j <= N; j++) {
                if(i == 0)
                    gcd[i][j] = j;
                else if(j == 0)
                    gcd[i][j] = i;
                else if(i >= j)
                    gcd[i][j] = gcd[j][i - j];
                else
                    gcd[i][j] = gcd[i][j - i];
            }

        long bad = 0;
        for(int dx = 0; dx <= M; dx++)
            for(int dy = 0; dy <= N; dy++) {
                int numPoints = gcd[dx][dy] + 1;

                long pos = -1;
                if(numPoints == 1)
                    pos = 1;
                else if(numPoints == 2)
                    pos = 6;
                else pos = (numPoints - 2) * 6 + 6;

                if(pos == -1)
                    throw new RuntimeException();

                pos = pos * (M - dx + 1) * (N - dy + 1);
                if(dx > 0 && dy > 0) {
                    pos *= 2;
                }

                bad = (bad + pos) % MOD;
            }

        ans = (ans - bad + MOD) % MOD;
        out.print(ans);
	}

    private long py(int p) {
        return (long)N / 2 + ((p == 0 || N % 2 == 1) ? 1 : 0);
    }

    private long px(int p) {
        return (long)M / 2 + ((p == 0 || M % 2 == 1) ? 1 : 0);
    }
}

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

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

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

    }

abstract class InputReader {

    public abstract int read();

    public int readInt() {
        return Integer.parseInt(readString());
    }

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

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

    }


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

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

class TaskD {
    public static final int MOD = 1000000007;
    private int N, M;
	public void solve(int testNumber, StreamInputReader in, PrintWriter out) {
        M = in.readInt();
        N = in.readInt();
        long ans = 0;
        for(int px0 = 0; px0 < 2; px0++)
        for(int py0 = 0; py0 < 2; py0++)
        for(int px1 = 0; px1 < 2; px1++)
        for(int py1 = 0; py1 < 2; py1++)
        for(int px2 = 0; px2 < 2; px2++)
        for(int py2 = 0; py2 < 2; py2++)
           if((px0 * (py1 - py2 + 2) + py0 * (px2 - px1 + 2) + px1 * py2 - px2 * py1 + 2) % 2 == 0) {
               long crt = 1;
               crt *= px(px0);
               crt *= px(px1);
               crt *= px(px2);
               crt %= MOD;
               crt *= py(py0);
               crt *= py(py1);
               crt *= py(py2);
               ans = (ans + crt) % MOD;
           }

        int[][] gcd = new int[4001][4001];
        for(int i = 0; i <= M; i++)
            for(int j = 0; j <= N; j++) {
                if(i == 0)
                    gcd[i][j] = j;
                else if(j == 0)
                    gcd[i][j] = i;
                else if(i >= j)
                    gcd[i][j] = gcd[j][i - j];
                else
                    gcd[i][j] = gcd[i][j - i];
            }

        long bad = 0;
        for(int dx = 0; dx <= M; dx++)
            for(int dy = 0; dy <= N; dy++) {
                int numPoints = gcd[dx][dy] + 1;

                long pos = -1;
                if(numPoints == 1)
                    pos = 1;
                else if(numPoints == 2)
                    pos = 6;
                else pos = (numPoints - 2) * 6 + 6;

                if(pos == -1)
                    throw new RuntimeException();

                pos = pos * (M - dx + 1) * (N - dy + 1);
                if(dx > 0 && dy > 0) {
                    pos *= 2;
                }

                bad = (bad + pos) % MOD;
            }

        ans = (ans - bad + MOD) % MOD;
        out.print(ans);
	}

    private long py(int p) {
        return (long)N / 2 + ((p == 0 || N % 2 == 1) ? 1 : 0);
    }

    private long px(int p) {
        return (long)M / 2 + ((p == 0 || M % 2 == 1) ? 1 : 0);
    }
}

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

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

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

    }

abstract class InputReader {

    public abstract int read();

    public int readInt() {
        return Integer.parseInt(readString());
    }

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

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

    }


import java.util.Scanner;

public class Solution1 {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        int c0 = in.nextInt();
        int d0 = in.nextInt();

        int[] a = new int[m + 1];
        int[] b = new int[m + 1];
        int[] c = new int[m + 1];
        int[] d = new int[m + 1];

        for (int i = 1; i <= m; i++) {
            a[i] = in.nextInt();
            b[i] = in.nextInt();
            c[i] = in.nextInt();
            d[i] = in.nextInt();
        }
        a[0] = n;
        b[0] = 1;
        c[0] = c0;
        d[0] = d0;
        int dp[][] = new int[n + 1][m + 1];

        for (int i = 0; i <= n; ++i) {
            for (int j = 0; j <= m; ++j) {
                for (int k = 0; k <= a[j] / b[j]; ++k) {
if(c[j] * k <= i)
                    dp[i][j] = Math.max(dp[i][j], d[j] * k + (j > 0 ? dp[i - k * c[j]][j - 1] : 0));
                }
}
            }
        }

        System.out.println(dp[n][m]);

    }
}


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.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

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

    static class div2C_C106Buns {
        int c0;
        int d0;
        int m;
        int doughAvailable;
        int[] cost;
        int[] stuffingAvailable;
        int[] stuffingNeeded;
        int[] doughNeeded;
        int memo;

        public void solve(int testNumber, InputReader in, OutputWriter out) {

            doughAvailable = in.nextInt();
            m = in.nextInt();
            c0 = in.nextInt();
            d0 = in.nextInt();
            cost = new int[m];
            stuffingAvailable = new int[m];
            stuffingNeeded = new int[m];
            doughNeeded = new int[m];

            memo = new int[102][102];

            for (int i = 0; i < memo.length; i++) {
                Arrays.fill(memo[i], -1);
            }

            for (int i = 0; i < m; i++) {
                stuffingAvailable[i] = in.nextInt();
                stuffingNeeded[i] = in.nextInt();
                doughNeeded[i] = in.nextInt();
                cost[i] = in.nextInt();
            }

            int ans = dp(doughAvailable, 0);

            out.print(ans);

        }

        int dp(int doughAvail, int i) {

            if (doughAvail == 0) return 0;

            //already taken sufficient m but still have dough use it with no stuffing
            if (i == m) return (doughAvail / c0) * d0;

            //try all combs of no stuffings
            //try all coming with a stuffing

            if (memo[doughAvail][i] != -1) return memo[doughAvail][i];

            int max = Integer.MIN_VALUE;

            for (int amountNoStuffing = 0; amountNoStuffing * c0 <= doughAvail; amountNoStuffing++) {
                max = Math.max(max, amountNoStuffing * d0 + dp(doughAvail - amountNoStuffing * c0, i + 1));
            }

            //take one of ms
            for (int amountOfStuffingOfM = 0;
                 doughAvail >= amountOfStuffingOfM * doughNeeded[i] && stuffingAvailable[i] >= amountOfStuffingOfM * stuffingNeeded[i];
                 amountOfStuffingOfM++) {

                max = Math.max(max, amountOfStuffingOfM * cost[i] + dp(doughAvail - amountOfStuffingOfM * doughNeeded[i], i + 1));
            }

            return memo[doughAvail][i] = max;
        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

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

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

        public void print(int i) {
            writer.print(i);
        }

    }

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

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

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

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

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

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

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

        }

    }
}


import java.util.ArrayList;
import java.util.Scanner;

public class D {
    static boolean[] vis;
    static boolean[] source, destination;
    static boolean[] interesting;
    static ArrayList<ArrayList<Integer>> graph;

    public static boolean dfs(int cur) {
        if (destination[cur])
            return interesting[cur]=true;
        vis[cur] = true;
        boolean interst = false;
        for (Integer i : graph.get(cur)) {
            if (!vis[i] ) {
                interst |= dfs(i);
            }
        }
        return interesting[cur] = interst;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        graph = new ArrayList<ArrayList<Integer>>();
        source=new boolean[n];
        destination=new boolean[n];
        interesting=new boolean[n];
        for (int i = 0; i < n; i++)
            graph.add(new ArrayList<Integer>());
        for (int i = 0; i < n; i++) {
            int val = sc.nextInt();
            if (val == 1) {
                source[i] = true;
            } else if (val == 2) {
                destination[i] = true;
            }
        }
        for(int i=0;i<m;i++){
            int f=sc.nextInt()-1;
            int s=sc.nextInt()-1;
            graph.get(f).add(s);
        }
        vis = new boolean[n];
        for (int i = 0; i < n; i++) {
            if (source[i]) {
                dfs(i);
            }
        }
        for (int i = 0; i < n; i++) {
            if (interesting[i]) {
                System.out.println(1);
            } else {
                System.out.println(0);
            }
        }
    }
}


/**
 * @author egaeus
 * @mail sebegaeusprogram@gmail.com
 * @veredict Not sended
 * @url <https://codeforces.com/problemset/problem/41/C>
 * @category ?
 * @date 2/07/2020
 **/

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

import static java.lang.Integer.*;
import static java.lang.Math.*;

public class CF41C {
    public static void main(String args[]) throws Throwable {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        for (String ln; (ln = in.readLine()) != null && !ln.equals(""); ) {
            String a = ln;
            char begin = a.charAt(0), last = a.charAt(a.length() - 1);
            a = a.substring(1, a.length() - 1).replaceAll("dot", ".");
            int index = a.lastIndexOf("at");
            a = a.substring(0, index) + "@" + a.substring(index + 2);
            System.out.println(begin + a + last);
        }
    }
}


import java.util.ArrayList;
import java.util.Scanner;

public class DrazilandFactorial {
    static long fact[] = {1,1,2,6,24,120,720,5040,40320,362880};

    static long func(long n){
        long ans = 1;
        while(n>0){
            long b = n%10;
            ans*=fact[ (int) b ];
            n/=10;
        }
        return ans;
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
         n = sc.nextInt();
        long f = sc.nextLong();
        funcTarget = func(f);
        rec(1,f,"");
        System.out.println(mx);
    }
    static int n;
    static long funcTarget;
    static long mx = Long.MIN_VALUE;
    static void rec(long cur,long target,String res){
        if((cur)==funcTarget){
            mx = Math.max(mx,Long.parseLong(res));
            return;
        }
        if(res.length()>n+1)return;
        rec(cur*fact[2],target,res+2);
        rec(cur*fact[3],target,res+3);
        rec(cur*fact[4],target,res+4);
        rec(cur*fact[5],target,res+5);
        rec(cur*fact[6],target,res+6);
        rec(cur*fact[7],target,res+7);
        rec(cur*fact[8],target,res+8);
        rec(cur*fact[9],target,res+9);

    }
}


import java.util.*;
import java.util.logging.Level;
import java.awt.Point;

import java.io.*;

public class tr0 {
	static PrintWriter out;
	static StringBuilder sb;
	static final double EPS = 1e-9;
	static long mod = 1000000007;
	static int inf = (int) 1e9 + 2;
	static long[] fac;
	static int[] si;
	static ArrayList<Integer> primes;
	static ArrayList<qu>[] ad;
	static ArrayList<qu>[] d;
	static edge[] ed;
	static int[] ch;
	static int[] occ;
	static long[][] adjMatrix;
	static Queue<Integer>[] can;
	static String s;
	static int[][] memo;
	static int n, m, r, k;
	static int[] o;
	static boolean[] t;
	static HashMap<Integer, Integer> pri;
	static TreeMap<qu, Integer> map;

	public static void main(String[] args) throws Exception {
		Scanner sc = new Scanner(System.in);
		out = new PrintWriter(System.out);
		n = sc.nextInt();
		int ans = 0;
		String s = sc.nextLine();
		sb = new StringBuilder();
		sb.append(s);
		for (int i = 25; i > 0; i--) {
			StringBuilder sb1 = new StringBuilder();
			for (int j = 0; j < sb.length(); j++) {
				if (sb.length() == 1) {
					break;
				}
				if (sb.charAt(j) == 'a' + i) {
					int st = j;
					while (j < sb.length() && sb.charAt(j) == 'a' + i) {
						j++;
					}
					int ed = j;
					if (st == 0 && ed==sb.length()) {
                         continue;
					}
					if(st==0 && sb.charAt(ed)=='a'+i-1) {
						ans+=ed-st;
					}
					else if(st!=0 && ed==sb.length() && sb.charAt(st-1)=='a'+i-1) {
						ans+=ed-st;
					}
					else if(st!=0 && ed!=sb.length() &&(sb.charAt(st-1)=='a'+i-1 || sb.charAt(ed)=='a'+i-1)) {
						ans+=ed-st;
					}
					else {
						sb1.append(sb.charAt(j));
					}
					j--;
				} else
					sb1.append(sb.charAt(j));
			//	sb=sb1;
			}
			sb=sb1;
		//	System.out.println(ans+" "+sb1);
		}
		out.print(ans);
		out.flush();
	}

	static boolean valid(int i, int j) {
		return i >= 0 && i < n && j >= 0 && j < m;
	}

	static long cal(int i, int j) {
		return (Math.min(i, n - r) - Math.max(0, i - r + 1) + 1) * 1l
				* (Math.min(j, m - r) - Math.max(0, j - r + 1) + 1);
	}

	static class qu implements Comparable<qu> {
		int a;
		int b;
		int w;
		int i;

		qu(int aa, int bb, int cc, int id) {
			a = aa;
			b = bb;
			w = cc;
			i = id;
		}

		public String toString() {
			return a + " " + b + " " + w + " " + i;
		}

		public int compareTo(qu o) {
			if (a == o.a)
				if (b == o.b)
					return i - o.i;
				else
					return b - o.b;
			return a - o.a;
		}
	}

	static class seg implements Comparable<seg> {
		int a;
		int b;
		long v;

		seg(int s, int e, long vv) {
			a = s;
			b = e;
			v = vv;
		}

		public String toString() {
			return a + " " + b + " " + v;
		}

		public int compareTo(seg o) {
			// if(a==o.a)
			return Long.compare(o.v, v);
			// return
		}
	}

	static class pair implements Comparable<pair> {
		int to;
		int number;

		pair(int t, int n) {
			number = n;
			to = t;
		}

		public String toString() {
			return to + " " + number;
		}

		@Override
		public int compareTo(pair o) {
			if (to == o.to)
				return number - o.number;
			return to - o.to;
		}

	}

	static long modPow(long a, long e)

	{
		long res = 1;
		while (e > 0) {
			if ((e & 1) == 1)
				res = (res * a) % mod;
			a = (a * a) % mod;
			e >>= 1;
		}
		return res;
	}

	static long inver(long x) {
		long a = x;
		long e = (mod - 2);
		long res = 1;
		while (e > 0) {
			if ((e & 1) == 1) {
				res = ((1l * res * a) % mod);
			}
			a = ((1l * a * a) % mod);
			e >>= 1;
		}
		return res % mod;
	}

	static class edge implements Comparable<edge> {
		int from;
		int to;
		int number;

		edge(int f, int t, int n) {
			from = f;
			to = t;
			number = n;
		}

		public String toString() {
			return from + " " + to + " " + number;
		}

		public int compareTo(edge f) {
			return f.number - number;
		}
	}

	static void seive(int N) {
		si = new int[N];
		primes = new ArrayList<>();
		si[1] = 1;
		for (int i = 2; i < N; i++) {
			if (si[i] == 0) {
				si[i] = i;
				primes.add(i);
			}
			for (int j = 0; j < primes.size() && primes.get(j) <= si[i] && (i * primes.get(j)) < N; j++)
				si[primes.get(j) * i] = primes.get(j);
		}
	}

	static long fac(int n) {
		if (n == 0)
			return fac[n] = 1;
		if (n == 1)
			return fac[n] = 1;
		long ans = 1;
		for (int i = 1; i <= n; i++)
			fac[i] = ans = (i % mod * ans % mod) % mod;
		return ans % mod;
	}

	static long gcd(long a, long b) {

		if (b == 0)
			return a;
		return gcd(b, a % b);
	}

	static class unionfind {
		int[] p;
		int[] size;
		int[] max;
		int num;

		unionfind(int n) {
			p = new int[n];
			size = new int[n];
			max = new int[n];
			for (int i = 0; i < n; i++) {
				p[i] = i;
				max[i] = i;
			}
			Arrays.fill(size, 1);
			num = n;
		}

		int findSet(int v) {
			if (v == p[v])
				return v;

			max[v] = Math.max(max[v], max[p[v]]);

			p[v] = findSet(p[v]);

			max[v] = Math.max(max[v], max[p[v]]);

			return p[v];
		}

		boolean sameSet(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			return false;
		}

		int max() {
			int max = 0;
			for (int i = 0; i < size.length; i++)
				if (size[i] > max)
					max = size[i];
			return max;
		}

		boolean combine(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			// System.out.println(num+" ppp");
			num--;
			if (size[a] > size[b]) {
				p[b] = a;
				max[a] = Math.max(max[a], max[b]);
				size[a] += size[b];

			} else {
				p[a] = b;
				max[b] = Math.max(max[a], max[b]);
				size[b] += size[a];
			}
			return false;
		}
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

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

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

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

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

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

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

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

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

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

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


import java.util.*;

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
       int n = Integer.parseInt(sc.nextLine());
       String s = sc.nextLine();
       System.out.println( get_ans(new StringBuilder(s),n));
    }

    private static long get_ans(StringBuilder s,int n){
        char c = '0';
        int ans = 0;
        boolean flag =false;
        for(int i=0;i<n;i++){
            if((i-ans!=0&&s.charAt(i-ans)-s.charAt(i-1-ans)==1)||(i-ans+1!=s.length()&&s.charAt(i-ans)-s.charAt(i+1-ans)==1)||(flag&&s.charAt(i-ans)-c==1)){
                c = s.charAt(i-ans);
                flag = true;
                s = s.deleteCharAt(i-ans);
                ans++;
            }
            else
                flag = false;
            while (s.length()!=1&&i-ans+1>0&&s.charAt(i-ans+1)-s.charAt(i-ans)==-1) {
                s.deleteCharAt(i - ans);
                ans++;
            }

        }
        return ans;
    }

}


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

public class Main
{
	static final int mod = (int)1e9+7;
	public static void main(String[] args) throws Exception
	{
		FastReader in = new FastReader();
		PrintWriter out = new PrintWriter(System.out);
		int n = in.nextInt();
		int m = in.nextInt();
		if(n < 7)
			out.println(m);
		else
		{
			int[][] adj = new int[n+1][n+1];
			int[][] e = new int[m][2];
			for(int i = 0; i < m; i++)
			{
				e[i][0] = in.nextInt();
				e[i][1] = in.nextInt();
				adj[e[i][0]][e[i][1]]++;
				adj[e[i][1]][e[i][0]]++;
			}
			int ans = 0;
			for(int i = 1; i < 7; i++)
			{
				int c = 0;
				for(int j = 1; j <= 7; j++)
				{
					if(adj[i][j] == 1 && adj[7][j] == 1)
						c++;
				}
				ans = Math.max(ans, m - c);
			}
			out.println(ans);
		}
		out.flush();
	}
}

class FastReader
{
	BufferedReader br;
	StringTokenizer st;

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

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

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

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

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


    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.io.Writer;
    import java.util.Arrays;
    import java.util.InputMismatchException;
    import java.util.*;
    import java.io.*;
    import java.math.*;
    public class Main7{

    static class Pair
        {
            int x;
            int y;
            public Pair(int x,int y)
            {
                this.x= x;
                this.y= y;
            }

        @Override
                public int hashCode()
                {
                    final int temp = 14;
                    int ans = 1;
                    ans =x*31+y*13;
                    return ans;
                }

                // Equal objects must produce the same
                // hash code as long as they are equal
            @Override
            public boolean equals(Object o)
            {
                if (this == o) {
                    return true;
                }
                if (o == null) {
                    return false;
                }
                if (this.getClass() != o.getClass()) {
                    return false;
                }
                Pair other = (Pair)o;
                if (this.x != other.x || this.y!=other.y) {
                    return false;
                }
                return true;
            }

        }
        static class Pair1
        {
            String x;
            int y;
            int z;

        }
        static class Compare
        {
            static void compare(Pair arr[], int n)
            {
                // Comparator to sort the pair according to second element
            /*    Arrays.sort(arr, new Comparator<Pair>() {
                    @Override public int compare(Pair p1, Pair p2)
                    {
                        if(p1.start>p2.start)
                        {
                            return 1;
                        }
                        else if(p1.start==p2.start)
                        {
                            return 0;
                        }
                        else
                        {
                            return -1;
                        }
                    }
                }); */
            }

        }

        public static long pow(long a, long b)
        {
            long result=1;
            while(b>0)
            {
                if (b % 2 != 0)
                {
                    result=(result*a)%998244353;
                    b--;
                }
                a=(a*a)%998244353;
                b /= 2;
            }
            return result;
        }
        public static long fact(long num)
        {
                    long value=1;
                    int i=0;
                    for(i=2;i<num;i++)
                    {
                        value=((value%mod)*i%mod)%mod;
                    }
                    return value;
                }
                public static long gcd(long a, long b)
                {
                    if (a == 0)
                        return b;
                    return gcd(b%a, a);
                }

        /*        public static long lcm(long a,long b)
                {
                    return a * (b / gcd(a, b));
                }
            */    public static long sum(int h)
                {
                    return (h*(h+1)/2);
                }
                public static void dfs(int parent,boolean[] visited,int[] dp)
                {
                    ArrayList<Integer> arr=new ArrayList<Integer>();
                    arr=graph.get(parent);
                    visited[parent]=true;
                    for(int i=0;i<arr.size();i++)
                    {
                        int num=(int)arr.get(i);
                        if(visited[num]==false)
                        {
                            dfs(num,visited,dp);
                        }
                        dp[parent]=Math.max(dp[num]+1,dp[parent]);
                    }
                }
            //    static int flag1=0;
                static int[] dis;
                static int mod=1000000007;
                static ArrayList<ArrayList<Integer>> graph;

                public static void bfs(int num,int size)
                {
                    boolean[] visited=new boolean[size+1];
                    Queue<Integer> q=new LinkedList<>();
                    q.add(num);
                    ans[num]=1;
                    visited[num]=true;
                    while(!q.isEmpty())
                    {
                        int x=q.poll();
                        ArrayList<Integer> al=graph.get(x);
                        for(int i=0;i<al.size();i++)
                        {
                            int y=al.get(i);
                            if(visited[y]==false)
                            {
                                q.add(y);
                                ans[y]=ans[x]+1;
                                visited[y]=true;
                            }
                        }
                    }
                }
                static int[] ans;

            //    static int[] a;
                public static int[] sort(int[] a)
                {
                    int n=a.length;
                    ArrayList<Integer> ar=new ArrayList<>();
                    for(int i=0;i<a.length;i++)
                    {
                        ar.add(a[i]);
                    }
                    Collections.sort(ar);
                    for(int i=0;i<n;i++)
                    {
                        a[i]=ar.get(i);
                    }
                    return a;
                }
                static public void main(String args[])throws IOException
                {
                    int n1=i();
					int m1=i();
					int[] a=new int[m1];
					int[] b=new int[m1];
					for(int i=0;i<m1;i++)
					{
						a[i]=i()-1;
						b[i]=i()-1;
					}
					int max=0;
					for(int i=6;i>=0;i--)
					{
						for(int j=6;j>=0;j--)
						{
							for(int k=6;k>=0;k--)
							{
								for(int l=6;l>=0;l--)
								{
									for(int m=6;m>=0;m--)
									{
										for(int n=6;n>=0;n--)
										{
											for(int o=6;o>=0;o--)
											{
												int ans=0;
												int[] x=new int[]{i,j,k,l,m,n,o};
												HashMap<ArrayList<Integer>,Integer> hash=new HashMap<>();
												for(int p=0;p<m1;p++)
												{
													int num=a[p];
													int num1=b[p];
													if(x[a[p]]==0 || x[b[p]]==0)
													{
														continue;
													}
													else
													{
														ArrayList<Integer> ar=new ArrayList<>();
														ar.add(x[a[p]]);
														ar.add(x[b[p]]);
														ArrayList<Integer> ar1=new ArrayList<>();
														ar1.add(x[b[p]]);
														ar1.add(x[a[p]]);
														if(hash.containsKey(ar)==false && hash.containsKey(ar1)==false)
														{
															ans++;
															hash.put(ar,1);
															ar.clear();
															ar.add(x[b[p]]);
															ar.add(x[a[p]]);
															hash.put(ar,1);
															if(ans==m1)
															{
																pln(m1+"");
																return;
															}

														}
													}
												}
												max=Math.max(ans,max);
											}
										}
									}

								}
							}
						}
					}
					pln(max+"");
                }

                /**/
                static InputReader in=new InputReader(System.in);
                    static OutputWriter out=new OutputWriter(System.out);
                    public static long l()
                    {
                        String s=in.String();
                        return Long.parseLong(s);
                    }
                    public static void pln(String value)
                    {
                        System.out.println(value);
                    }
                    public static int i()
                    {
                        return in.Int();
                    }
                    public static String s()
                    {
                        return in.String();
                    }
        }

            class InputReader {

                private InputStream stream;
                private byte[] buf = new byte[1024];
                private int curChar;
                private int numChars;
                private SpaceCharFilter filter;

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

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

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

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

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

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

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

            class OutputWriter {
                private final PrintWriter writer;

                public OutputWriter(OutputStream outputStream) {
                    writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
                }

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

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

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

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

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

                }

                class IOUtils {

                public static int[] readIntArray(InputReader in, int size) {
                    int[] array = new int[size];
                    for (int i = 0; i < size; i++)
                        array[i] = in.Int();
                    return array;
                }

                }