import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.TreeSet;
import java.util.function.BiFunction;

public class Main{
	static int n;
	static int mod = 1000000007;
	static long[][] A;
	public static void main(String[] args){
		FastScanner sc = new FastScanner();
		Mathplus mp = new Mathplus();
		PrintWriter out = new PrintWriter(System.out);

		n = sc.nextInt();
		int k = sc.nextInt();
		int num = 0;
		int[] a = new int[n];
		for(int i=0;i<n;i++){
			a[i] = sc.nextInt();
			num+=a[i];
		}
		int d = 0;
		for(int i=0;i<n-num;i++){
			if(a[i]==1) d ++;
		}
		long alle = n*(n-1)/2;
		long mot = mp.rev(alle);
		A = new long[n/2+1][n/2+1];
		for(int i=0;i<=n/2+1;i++){
			if(i!=0){
				A[i][i-1] = i * i * mot%mod;
			}
			if(i!=n/2+1){
				A[i][i+1] =Math.max(0,(n-num-i)) * Math.max(0,num-i) * mot % mod;
			}
			A[i][i] = Math.max(alle - i * i-Math.max(0,n-num-i) * Math.max(0,num-i),0)*mot%mod;
		}
		long[][] ans = pow(A,k);

		System.out.println(ans[d][0]);
	}
	private static long[][] pow(long[][] a2, long k) {
		if(k==1){
			return a2;
		}else{
			if(k%2==0){
				long[][] val = pow(a2,k/2);
				return mul(val,val);
			}else{
				return mul(pow(a2,k-1),A);
			}
		}
	}
	private static long[][] mul(long[][] a, long[][] b) {
		long[][] c = new long[n/2+1][n/2+1];
		for(int i=0;i<n/2+1;i++){
			for(int j=0;j<n/2+1;j++){
				for(int k=0;k<n/2+1;k++){
					c[i][j] += a[i][k] * b[k][j];
					c[i][j] %= mod;
				}
			}
		}
		return c;
	}

}

class SegmentTree<T,E>{
	int N;
	BiFunction<T,T,T> f;
	BiFunction<T,E,T> g;
	T d1;
	ArrayList<T> dat;
	SegmentTree(BiFunction<T,T,T> F,BiFunction<T,E,T> G,T D1,T[] v){
		int n = v.length;
		f = F;
		g = G;
		d1 = D1;
		init(n);
		build(v);
	}

	void init(int n) {
		N = 1;
		while(N<n)N*=2;
		dat = new ArrayList<T>();
	}

	void build(T[] v) {
		for(int i=0;i<2*N;i++) {
			dat.add(d1);
		}
		for(int i=0;i<v.length;i++) {
			dat.set(N+i-1,v[i]);
		}
		for(int i=N-2;i>=0;i--) {
			dat.set(i,f.apply(dat.get(i*2+1),dat.get(i*2+2)));
		}
	}

	void update(int k,E a) {
		k += N-1;
		dat.set(k,g.apply(dat.get(k),a));
		while(k>0){
			k = (k-1)/2;
			dat.set(k,f.apply(dat.get(k*2+1),dat.get(k*2+2)));
		}
	}

	T query(int a,int b, int k, int l ,int r) {
		if(r<=a||b<=l) return d1;
		if(a<=l&&r<=b) return dat.get(k);
		T vl = query(a,b,k*2+1,l,(l+r)/2);
		T vr = query(a,b,k*2+2,(l+r)/2,r);
		return f.apply(vl, vr);
	}
	T query(int a,int b){
		return query(a,b,0,0,N);
	}

}

class LazySegmentTree<T,E> extends SegmentTree<T,E>{
	BiFunction<E,E,E> h;
	BiFunction<E,Integer,E> p = (E a,Integer b) ->{return a;};
	E d0;
	ArrayList<E> laz;
	LazySegmentTree(BiFunction<T,T,T> F,BiFunction<T,E,T> G,BiFunction<E,E,E> H,T D1,E D0,T[] v){
		super(F,G,D1,v);
		int n = v.length;
		h = H;
		d0 = D0;
		Init(n);
	}
	void build() {

	}
	void Init(int n){
		laz = new ArrayList<E>();
		for(int i=0;i<2*N;i++) {
			laz.add(d0);
		}
	}

	void eval(int len,int k) {
		if(laz.get(k).equals(d0)) return;
		if(k*2+1<N*2-1) {
			laz.set(k*2+1,h.apply(laz.get(k*2+1),laz.get(k)));
			laz.set(k*2+2,h.apply(laz.get(k*2+2),laz.get(k)));
		}
		dat.set(k,g.apply(dat.get(k), p.apply(laz.get(k), len)));
		laz.set(k,d0);
	}

	T update(int a,int b,E x,int k,int l,int r) {
		eval(r-l,k);
		if(r<=a||b<=l) {
			return dat.get(k);
		}
		if(a<=l&&r<=b) {
			laz.set(k,h.apply(laz.get(k),x));
			return g.apply(dat.get(k),p.apply(laz.get(k),r-l));
		}
		T vl = update(a,b,x,k*2+1,l,(l+r)/2);
		T vr = update(a,b,x,k*2+2,(l+r)/2,r);
		dat.set(k,f.apply(vl,vr));
		return dat.get(k);

	}

	T update(int a,int b,E x) {
		return update(a,b,x,0,0,N);
	}

	T query(int a,int b,int k,int l,int r) {
		eval(r-l,k);
		if(r<=a||b<=l) return d1;
		if(a<=l&&r<=b) return dat.get(k);
		T vl = query(a,b,k*2+1,l,(l+r)/2);
		T vr = query(a,b,k*2+2,(l+r)/2,r);
		return f.apply(vl, vr);
	}

	T query(int a,int b){
		return query(a,b,0,0,N);
	}

}
class UnionFindTree {
	int[] root;
	int[] rank;
	int[] size;
	UnionFindTree(int N){
		root = new int[N];
		rank = new int[N];
		size = new int[N];
		for(int i=0;i<N;i++){
			root[i] = i;
			size[i] = 1;
		}
	}

	public int find(int x){
		if(root[x]==x){
			return x;
		}else{
			return find(root[x]);
		}
	}

	public void unite(int x,int y){
		x = find(x);
		y = find(y);
		if(x==y){
			return;
		}else{
			if(rank[x]<rank[y]){
				root[x] = y;
				size[y] += size[x];
			}else{
				root[y] = x;
				size[x] += size[y];
				if(rank[x]==rank[y]){
					rank[x]++;
				}
			}
		}
	}

	public boolean same(int x,int y){
		return find(x)==find(y);
	}

}

class ParticalEternalLastingUnionFindTree extends UnionFindTree{
	int[] time;
	int now;
	ParticalEternalLastingUnionFindTree(int N){
		super(N);
		time = new int[N];
		for(int i=0;i<N;i++) {
			time[i] = 1000000007;
		}
	}

	public int find(int t,int i) {
		if(time[i]>t) {
			return i;
		}else {
			return find(t,root[i]);
		}
	}

	public void unite(int x,int y,int t) {
		now = t;
		x = find(t,x);
		y = find(t,y);
		if(x==y)return;
		if(rank[x]<rank[y]){
			root[x] = y;
			size[y] += size[x];
			time[x] = t;
		}else{
			root[y] = x;
			size[x] += size[y];
			if(rank[x]==rank[y]){
				rank[x]++;
			}
			time[y] = t;
		}
	}

	public int sametime(int x,int y) {
		if(find(now,x)!=find(now,y)) return -1;
		int ok = now;
		int ng = 0;
		while(ok-ng>1) {
			int mid = (ok+ng)/2;
			if(find(mid,x)==find(mid,y)) {
				ok = mid;
			}else {
				ng = mid;
			}
		}
		return ok;
	}

}
class Graph {
	ArrayList<Edge>[] list;
	int size;

	TreeSet<LinkEdge> Edges = new TreeSet<LinkEdge>(new LinkEdgeComparator());

	@SuppressWarnings("unchecked")
	Graph(int N){
		size = N;
		list = new ArrayList[N];
		for(int i=0;i<N;i++){
			list[i] = new ArrayList<Edge>();
		}
	}

	void addEdge(int a,int b){
		list[a].add(new Edge(b,1));
	}

	void addWeightedEdge(int a,int b,long c){
		list[a].add(new Edge(b,c));
	}

	void addEgdes(int[] a,int[] b){
		int size = a.length;
		for(int i=0;i<size;i++){
			list[a[i]].add(new Edge(b[i],1));
		}
	}

	void addWeighterEdges(int[] a ,int[] b ,int[] c){
		int size = a.length;
		for(int i=0;i<size;i++){
			list[a[i]].add(new Edge(b[i],c[1]));
		}
	}

	long[] bfs(int s){
		long[] L = new long[size];
		for(int i=0;i<size;i++){
			L[i] = -1;
		}
		L[s] = 0;
		ArrayDeque<Integer> Q = new ArrayDeque<Integer>();
		Q.add(s);

		while(!Q.isEmpty()){
			int v = Q.poll();
			for(Edge e:list[v]){
				int w = e.to;
				long c = e.cost;
				if(L[w]==-1){
					L[w] = L[v] + c;
					Q.add(w);
				}
			}
		}

		return L;
	}

	long[] dijkstra(int s){
		long[] L = new long[size];
		for(int i=0;i<size;i++){
			L[i] = -1;
		}
		int[] visited = new int[size];
		L[s] = 0;
		PriorityQueue<Pair> Q = new PriorityQueue<Pair>(new SampleComparator());
		Q.add(new Pair(0,s));

		while(!Q.isEmpty()){

			Pair C = Q.poll();
			if(visited[(int)C.b]==0){
				L[(int)C.b] = C.a;
				visited[(int) C.b] = 1;
				for(Edge D:list[(int) C.b]){
					Q.add(new Pair(L[(int)C.b]+D.cost,D.to));
				}
			}
		}

		return L;
	}
	long[] maxtra(int s,long l){
		long[] L = new long[size];
		for(int i=0;i<size;i++){
			L[i] = -1;
		}
		int[] visited = new int[size];
		L[s] = -1;
	;
		PriorityQueue<Pair> Q = new PriorityQueue<Pair>(new SampleComparator());
		Q.add(new Pair(l,s));

		while(!Q.isEmpty()){

			Pair C = Q.poll();
			if(visited[(int)C.b]==0){
				L[(int)C.b] = C.a;
				visited[(int) C.b] = 1;
				for(Edge D:list[(int) C.b]){
					Q.add(new Pair(Math.max(L[(int)C.b],D.cost),D.to));
				}
			}
		}

		return L;
	}
	long Kruskal(){
		long ans = 0;
		for(int i=0;i<size;i++) {
			for(Edge e:list[i]) {
				Edges.add(new LinkEdge(e.cost,i,e.to));
			}
		}
		UnionFindTree UF = new UnionFindTree(size);
		for(LinkEdge e:Edges){
			if(e.a>=0&&e.b>=0) {
				if(!UF.same(e.a,e.b)){
					ans += e.L;
					UF.unite(e.a,e.b);
				}
			}
		}

		return ans;
	}

	ArrayList<Integer> Kahntsort(){

		ArrayList<Integer> ans = new ArrayList<Integer>();
		PriorityQueue<Integer> q = new PriorityQueue<Integer>();
		int[] in = new int[size];
		for(int i=0;i<size;i++) {
			for(Edge e:list[i]) {
				in[e.to]++;
			}
		}
		for(int i=0;i<size;i++) {
			if(in[i]==0) {
				q.add(i);
			}
		}
		while(!q.isEmpty()) {
			int v = q.poll();
			ans.add(v);
			for(Edge e:list[v]) {
				in[e.to]--;
				if(in[e.to]==0) {
					q.add(e.to);
				}
			}
		}
		for(int i=0;i<size;i++) {
			if(in[i]>0)return new ArrayList<Integer>();
		}
		return ans;
	}

	RootedTree dfsTree(int i) {
		int[] used = new int[size];
		RootedTree r = new RootedTree(size);
		dfsTree(i,used,r);
		return r;

	}

	private void dfsTree(int i, int[] used, RootedTree r) {
		used[i] = 1;
		for(Edge e:list[i]) {
			if(used[e.to]==0) {
				r.list[i].add(e);
				used[e.to] = 1;
				dfsTree(i,used,r);
			}
		}

	}
}

class Tree extends Graph{

	public Tree(int N) {
		super(N);
	}

	long[] tyokkei(){
		long[] a = bfs(0);

		System.out.println();
		int maxdex = -1;
		long max = 0;
		for(int i=0;i<size;i++){
			if(max<a[i]){
				max = a[i];
				maxdex = i;
			}
		}

		long[] b = bfs(maxdex);
		System.out.println();
		int maxdex2 = -1;
		long max2 = 0;
		for(int i=0;i<size;i++){
			if(max2<b[i]){
				max2 = b[i];
				maxdex2 = i;
			}
		}
		long[] ans = {max2,maxdex,maxdex2};
		return ans;
	}

}

class RootedTree extends Graph{

	RootedTree(int N){
		super(N);
	}

}
class LinkEdge{
	long L;
	int a ;
	int b;
	LinkEdge(long l,int A,int B){
		L = l;
		a = A;
		b = B;
	}
	public boolean equals(Object o){
		LinkEdge O = (LinkEdge) o;
		if(O.a==this.a&&O.b==this.b&&O.L==this.L){
			return true;
		}else{
			return false;
		}

	}

	public int hashCode(){
		return Objects.hash(L,a,b);
	}

}

class Edge{
	int to;
	long cost;

	Edge(int a,long b){
		to = a;
		cost = b;
	}

}
class LinkEdgeComparator implements Comparator<LinkEdge>{
	public int compare(LinkEdge P, LinkEdge Q) {
		long temp = P.L-Q.L;
		if(temp==0){
			if(P.a>Q.a){
				return 1;
			}else{
				if(P.b>Q.b){
					return 1;
				}else{
					return -1;
				}
			}

		}
		if(temp>=0){
			return 1;
		}else{
			return -1;
		}
	}

}
class Pair{
	long a;
	long b;

	Pair(long p,long q){
		this.a = p;
		this.b = q;
	}

	public boolean equals(Object o){
		Pair O = (Pair) o;
		if(O.a==this.a&&O.b==this.b){
			return true;
		}else{
			return false;
		}

	}

	public int hashCode(){
		return Objects.hash(a,b);
	}

}

class SampleComparator implements Comparator<Pair>{
	public int compare(Pair P, Pair Q) {
		long temp = P.a-Q.a;
		if(temp==0){
			if(P.b>Q.b){
				return 1;
			}else{
				return -1;
			}

		}
		if(temp>=0){
			return 1;
		}else{
			return -1;
		}
	}

}

class LongIntPair{
	long a;
	int b;

	LongIntPair(long p,int q){
		this.a = p;
		this.b = q;
	}

	public boolean equals(Object o){
		Pair O = (Pair) o;
		if(O.a==this.a&&O.b==this.b){
			return true;
		}else{
			return false;
		}

	}

	public int hashCode(){
		return Objects.hash(a,b);
	}

}

class LongIntSampleComparator implements Comparator<LongIntPair>{
	public int compare(LongIntPair P, LongIntPair Q) {
		long temp = P.a-Q.a;
		if(temp==0){
			if(P.b>Q.b){
				return 1;
			}else{
				return -1;
			}

		}
		if(temp>=0){
			return 1;
		}else{
			return -1;
		}
	}

}

class FastScanner {
    private final java.io.InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;
    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        }else{
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }
    private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
    private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
    private void skipUnprintable() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++;}
    public boolean hasNext() { skipUnprintable(); return hasNextByte();}
    public String next() {
        if (!hasNext()) throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while(isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    public long nextLong() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return (minus ? -n : n);
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
    public int nextInt() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return (int) (minus ? -n : n);
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
}

class Mathplus{
	int mod = 1000000007;
	long[] fac = new long[1000001];
	long[][] combt = new long[2001][2001];
	long[][] permt = new long[2001][2001];
	boolean isBuild = false;
	boolean isBuildc = false;
	boolean isBuildp = false;
	int mindex = -1;
	int maxdex = -1;

	void buildFac(){
		fac[0] = 1;
		for(int i=1;i<=1000000;i++){
			fac[i] = (fac[i-1] * i)%mod;
		}
		isBuild = true;
	}

	void buildComb() {
		for(int i=0;i<=2000;i++) {
			combt[i][0] = 1;
		}
		for(int j=1;j<=2000;j++) {
			combt[j][j] = 1;
			for(int i=j+1;i<=2000;i++) {
				combt[i][j] = combt[i-1][j-1] + combt[i-1][j];
				if(combt[i][j]>=mod)combt[i][j]-=mod;
			}

		}
		isBuildc = false;
	}

	void buildPerm() {
		for(int i=0;i<=2000;i++) {
			permt[i][0] = 1;
		}
		if(!isBuild)buildFac();
		for(int i=1;i<=2000;i++) {
			for(int j=1;j<=i;j++) {
				permt[i][j] = permt[i][j-1]*(i-j+1);
				permt[i][j] %= mod;
			}
		}
		isBuildp = true;
	}

	public int isBigger(int[] d, int i) {
		int ok = d.length;
		int ng = -1;
		while(Math.abs(ok-ng)>1) {
			int mid = (ok+ng)/2;
			if(d[mid]>i) {
				ok = mid;
			}else {
				ng = mid;
			}
		}
		return ok;
	}

	public int isSmaller(int[] d, int i) {
		int ok = -1;
		int ng = d.length;
		while(Math.abs(ok-ng)>1) {
			int mid = (ok+ng)/2;
			if(d[mid]<i) {
				ok = mid;
			}else {
				ng = mid;
			}
		}
		return ok;
	}

	public HashSet<Integer> primetable(int m) {
		HashSet<Integer> pt = new HashSet<Integer>();
		for(int i=2;i<=m;i++) {
			boolean b = true;
			for(int d:pt) {
				if(i%d==0) {
					b = false;
					break;
				}
			}
			if(b) {
				pt.add(i);
			}
		}
		return pt;
	}

	long max(long[] a){
		long max = 0;
		for(int i=0;i<a.length;i++){
			if(max<a[i]){
				max =a[i];
				maxdex = i;
			}
		}
		return max;
	}
	int max(int[] a){
		int max = 0;
		for(int i=0;i<a.length;i++){
			if(max<a[i]){
				max =a[i];
				maxdex = i;
			}
		}
		return max;
	}
	long min(long[] a){
		long min = Long.MAX_VALUE;
		for(int i=0;i<a.length;i++){
			if(min>a[i]){
				min =a[i];
				mindex = i;
			}
		}
		return min;
	}
	int min(int[] a){
		int min = Integer.MAX_VALUE;
		for(int i=0;i<a.length;i++){
			if(min>a[i]){
				min =a[i];
				mindex = i;
			}
		}
		return min;
	}
	long sum(long[] a){
		long sum = 0;
		for(int i=0;i<a.length;i++){
			sum += a[i];
		}
		return sum;
	}
	long sum(int[] a){
		long sum = 0;
		for(int i=0;i<a.length;i++){
			sum += a[i];
		}
		return sum;
	}

	long gcd(long a, long b){
		if(a<b){
			a^=b;
			b^=a;
			a^=b;
		}
		if(a%b==0){
			return b;
		}else{
			return gcd(b,a%b);
		}
	}

	long lcm(long a, long b){
		return a / gcd(a,b) * b;
	}

	public long perm(int a,int num) {
		if(a<2000&&num<2000) {
			if(!isBuildp) {
				buildPerm();
				isBuildp = true;
 			}
			return permt[a][num];
		}
		if(!isBuild) {
			buildFac();
		}
		return fac[a] * (rev(fac[a-num]))%mod;
	}
	public long comb(int a,int num){
		if(a<2000&&num<2000) {
			if(!isBuildc) {
				buildComb();
				isBuildc = true;
 			}
			return combt[a][num];
		}
		if(!isBuild){
			buildFac();
		}
		return fac[a] * (rev(fac[num])*rev(fac[a-num])%mod)%mod;
	}

	long rev(long l) {
		return pow(l,mod-2);
	}

	long pow(long l, int i) {
		if(i==0){
			return 1;
		}else{
			if(i%2==0){
				long val = pow(l,i/2);
				return val * val % mod;
			}else{
				return pow(l,i-1) * l % mod;
			}
		}
	}

}


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.StringTokenizer;

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);
    solve(in,out);
    out.close();
  }

  private static final int MOD = (int)1e9 + 7;

  private static long add(long a, long b) {
	  a += b;
	  if (a >= MOD) {
		  a -= MOD;
	  }
	  return a;
  }

  private static long pow(long a, int b) {
	  long ans = 1;
	  while (b > 0) {
		  if ((b % 2) > 0) {
			  ans = ans * a %MOD;
		  }
		  a = a * a % MOD;
		  b >>= 1;
	  }
	  return ans;
  }

  private static void solve(InputReader in, PrintWriter out) {
	  int n = in.nextInt();
	  long m = in.nextLong();
	  if (m == 1) {
		  out.print(n + 1);
		  return;
	  }
	  long dp[] = new long[n + 1];
	  dp[0] = 1;
	  long sum  = 1;
	  for (int i = 1; i <= n; i++) {
		  dp[i] = sum;
		  dp[i] = dp[i] * m % MOD * pow(m - 1, MOD - 2) % MOD;
		  sum = add(sum, dp[i]);
	  }
	  long ans = 0;
	  for (int i = 0; i <= n; i++) {
		  ans = add(ans, dp[i] * pow(m, n - i) % MOD * pow(m - 1, i) % MOD);
	  }
	  out.print(ans);
  }

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

  }
}


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

public final class diff_subs
{
    static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	static FastScanner sc=new FastScanner(br);
    static PrintWriter out=new PrintWriter(System.out);
	static Random rnd=new Random();
	static long mod=(long)(1e9+7);
	static long[] fact,inv_fact;
	static int maxn=(int)(1e6+6);

	static long pow(long a,long b)
	{
		long x=1,y=a;

		while(b>0)
		{
			if(b%2==1)
			{
				x=(x*y)%mod;
			}

			y=(y*y)%mod;b=b/2;
		}

		return x;
	}

	static void build()
	{
		fact=new long[maxn];inv_fact=new long[maxn];fact[0]=1;

		for(int i=1;i<maxn;i++)
		{
			fact[i]=(fact[i-1]*i)%mod;
		}

		inv_fact[maxn-1]=pow(fact[maxn-1],mod-2);

		for(int i=maxn-2;i>=0;i--)
		{
			inv_fact[i]=(inv_fact[i+1]*(i+1))%mod;
		}
	}

	static long C(int n,int r)
	{
		long val1=fact[n],val2=inv_fact[r],val3=inv_fact[n-r];

		long mul=(val2*val3)%mod;

		return (val1*mul)%mod;
	}

    public static void main(String args[]) throws Exception
    {
		build();

		int n=sc.nextInt(),m=sc.nextInt();

		if(m==1)
		{
			out.println(n+1);
		}

		else
		{
			long curr=m,res=0,xx=pow(m-1,n-1),zz=pow(m-1,mod-2);

			for(int s=1;s<=n;s++)
			{
				// for all i+j=s...

				long now=(curr*xx)%mod;

				// sum of all binomial cofficients, such that i+j=s, i>=1,j>=0...

				long sum=C(n,s-1);

				long mul=(now*sum)%mod;

				res=(res+mul)%mod;

				curr=(curr*m)%mod;

				xx=(xx*zz)%mod;
			}

			res=(res+pow(m,n))%mod;

			out.println(res);
		}

		out.close();
    }
}
class FastScanner
{
    BufferedReader in;
    StringTokenizer st;

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

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

	public String next() throws Exception {
		return nextToken().toString();
	}

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

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

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


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

public class CF660E {
	static int M = 1000000007;
	static int mul(int a, int b) {
		return (int) ((long) a * b % M);
	}
	static int pow(int a, int k) {
		if (k == 0)
			return 1;
		int p = pow(a, k / 2);
		p = mul(p, p);
		if (k % 2 == 1)
			p = mul(p, a);
		return p;
	}
	static int gcd_(int a, int b, int[] xy) {
		if (b == 0) {
			xy[0] = 1;
			xy[1] = 0;
			return a;
		} else {
			int d = gcd_(b, a % b, xy);
			int t = xy[0] - a / b * xy[1];
			xy[0] = xy[1];
			xy[1] = t;
			return d;
		}
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		int[] ff = new int[n + 1];
		int[] gg = new int[n + 1];
		ff[0] = gg[0] = 1;
		int[] xy = { 0, 0 };
		for (int i = 1; i <= n; i++) {
			gcd_(i, M, xy);
			int inv = (xy[0] % M + M) % M;
			ff[i] = mul(ff[i - 1], i);
			gg[i] = mul(gg[i - 1], inv);
		}
		int c = pow(m, n);
		for (int s = 1; s <= n; s++) {
			int a = mul(pow(m, s), pow(m - 1, n - s));
			a = mul(a, ff[n]);
			a = mul(a, gg[s - 1]);
			a = mul(a, gg[n - s + 1]);
			c = (c + a) % M;
		}
		System.out.println(c);
	}
}


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.StringTokenizer;

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);
    solve(in,out);
    out.close();
  }

  private static final int MOD = (int)1e9 + 7;

  private static long add(long a, long b) {
	  a += b;
	  if (a >= MOD) {
		  a -= MOD;
	  }
	  return a;
  }

  private static long pow(long a, int b) {
	  long ans = 1;
	  while (b > 0) {
		  if ((b % 2) > 0) {
			  ans = ans * a %MOD;
		  }
		  a = a * a % MOD;
		  b >>= 1;
	  }
	  return ans;
  }

  private static void solve(InputReader in, PrintWriter out) {
	  int n = in.nextInt();
	  long m = in.nextLong();
	  long ans = pow(m, n);
	  for (int i = 1; i <= n; i++) {
		  ans = add(ans, pow(2 * m - 1, i - 1) * pow(m, n - i + 1) % MOD);
	  }
	  out.print(ans);
  }

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

  }
}


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

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

    static class A1DeathStarsEasy {
        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int n = in.nextInt();
            char[][] original = new char[n][n];
            for (int i = 0; i < n; i++) {
                original[i] = in.nextLine().toCharArray();
            }
            char[][] copy = new char[n][n];
            for (int i = 0; i < n; i++) {
                copy[i] = in.nextLine().toCharArray();
            }
            for (int i = 0; i < 4; i++) {
                boolean eq = true;
                for (int j = 0; j < n && eq; j++) {
                    for (int k = 0; k < n && eq; k++) {
                        if (copy[j][k] != original[j][k]) {
                            eq = false;
                        }
                    }
                }
                if (eq) {
                    out.println("Yes");
                    return;
                }
                char[][] flipped = new char[n][n];
                for (int j = 0; j < n; j++) {
                    for (int k = 0; k < n; k++) {
                        flipped[j][n - k - 1] = copy[j][k];
                    }
                }
                eq = true;
                for (int j = 0; j < n && eq; j++) {
                    for (int k = 0; k < n && eq; k++) {
                        if (flipped[j][k] != original[j][k]) {
                            eq = false;
                        }
                    }
                }
                if (eq) {
                    out.println("Yes");
                    return;
                }
                copy = nextRotation(copy, n);
            }
            out.println("No");
        }

        private char[][] nextRotation(char[][] ch, int n) {
            char[][] ans = new char[n][n];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    ans[i][j] = ch[n - 1 - j][i];
                }
            }
            return ans;
        }

    }

    static class FastScanner {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer;
        private int bytesRead;

        public FastScanner(InputStream inputStream) {
            din = new DataInputStream(inputStream);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String nextLine() {
            byte[] buf = new byte[64];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') {
                    break;
                }
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

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

            if (neg) {
                return -ret;
            }
            return ret;
        }

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

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

    }
}


import java.lang.*;
import java.util.*;

public class deathStar{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        char[][] arr1=new char[n][n];
        char[][] arr2=new char[n][n];
        sc.nextLine();
        for(int i=0; i<n; i++){
            arr1[i]=sc.nextLine().toCharArray();
        }

        for(int i=0; i<n; i++){
            arr2[i]=sc.nextLine().toCharArray();
        }

        deathStar ds=new deathStar();
        boolean result=ds.isEqual(arr1,arr2,n);
        if(!result){
            int res=ds.check(arr1,arr2,n);
            if(res!=0){
                ds.flip(arr1,n,true);
                result=ds.isEqual(arr1,arr2,n);
                if(!result) res=ds.check(arr1,arr2,n);
                else{
                    System.out.println("YES");
                    return;
                }
            }
            if(res!=0){
                ds.flip(arr1,true);
                ds.flip(arr1,false);
                result=ds.isEqual(arr1,arr2,n);
                if(!result) res=ds.check(arr1,arr2,n);
                else{
                    System.out.println("YES");
                    return;
                }
            }
            if(res!=0) System.out.println("NO");
        }
        else System.out.println("YES");
    }

    public void flip(char[][] arr1,int n, boolean flipV){
        for(int j=0; j<n; j++){
            for(int i=0; i<n; i++){

                int a=(!flipV)?i:j;
                int b=(!flipV)?j:i;
                int c=(!flipV)?n-1-i:j;
                int d=(!flipV)?j:n-1-i;

                char temp=arr1[a][b];
                arr1[a][b]=arr1[c][d];
                arr1[c][d]=temp;
            }
        }
    }

    public void flip(char[][] arr1,int n, boolean flipV){
        for(int j=0; j<n; j++){
            for(int i=0; i<n; i++){
                char temp=arr1[j][i];
                arr1[j][i]=arr1[j][n-1-i];
                arr1[j][n-1-i]=temp;
            }
        }
    }

    public int check(char[][] arr1,char[][] arr2, int n){
        int i=0;
        while(i<3){
            rotate(arr1,n);
            if(isEqual(arr1,arr2,n)){
                System.out.println("YES");
                return 0;
            }
            i++;
        }
        rotate(arr1,n);
        return -1;
    }

    public boolean isEqual(char[][] arr1,char[][] arr2, int n){
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                if(arr1[i][j]!=arr2[i][j]){
                    return false;
                }
            }
        }
        return true;
    }

    public void rotate(char[][] arr, int n){
        for(int layer=0; layer<n/2; layer++){
            int first=layer;
            int last=n-1-layer;
            int offset=0;
            for(int j=first; j<last; j++){
                char top=arr[first][j];
                arr[first][j]=arr[last-offset][first];
                arr[last-offset][first]=arr[last][last-offset];
                arr[last][last-offset]=arr[j][last];
                arr[j][last]=top;
                offset++;
            }
        }
    }
}


import java.lang.*;
import java.util.*;

public class deathStar{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        char[][] arr1=new char[n][n];
        char[][] arr2=new char[n][n];
        sc.nextLine();
        for(int i=0; i<n; i++){
            arr1[i]=sc.nextLine().toCharArray();
        }

        for(int i=0; i<n; i++){
            arr2[i]=sc.nextLine().toCharArray();
        }

        deathStar ds=new deathStar();
        boolean result=ds.isEqual(arr1,arr2,n);
        if(!result){
            int res=ds.check(arr1,arr2,n);
            if(res!=0){
                ds.flip(arr1,n,true);
                result=ds.isEqual(arr1,arr2,n);
                if(!result) res=ds.check(arr1,arr2,n);
                else{
                    System.out.println("YES");
                    return;
                }
            }
            if(res!=0){
                ds.flip(arr1,true);
                ds.flip(arr1,false);
                result=ds.isEqual(arr1,arr2,n);
                if(!result) res=ds.check(arr1,arr2,n);
                else{
                    System.out.println("YES");
                    return;
                }
            }
            if(res!=0) System.out.println("NO");
        }
        else System.out.println("YES");
    }

    public void flip(char[][] arr1,int n, boolean flipV){
        for(int j=0; j<n; j++){
            for(int i=0; i<n; i++){

                int a=(!flipV)?i:j;
                int b=(!flipV)?j:i;
                int c=(!flipV)?n-1-i:j;
                int d=(!flipV)?j:n-1-i;

                char temp=arr1[a][b];
                arr1[a][b]=arr1[c][d];
                arr1[c][d]=temp;
            }
        }
    }

    public int check(char[][] arr1,char[][] arr2, int n){
        int i=0;
        while(i<3){
            rotate(arr1,n);
            if(isEqual(arr1,arr2,n)){
                System.out.println("YES");
                return 0;
            }
            i++;
        }
        rotate(arr1,n);
        return -1;
    }

    public boolean isEqual(char[][] arr1,char[][] arr2, int n){
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                if(arr1[i][j]!=arr2[i][j]){
                    return false;
                }
            }
        }
        return true;
    }

    public void rotate(char[][] arr, int n){
        for(int layer=0; layer<n/2; layer++){
            int first=layer;
            int last=n-1-layer;
            int offset=0;
            for(int j=first; j<last; j++){
                char top=arr[first][j];
                arr[first][j]=arr[last-offset][first];
                arr[last-offset][first]=arr[last][last-offset];
                arr[last][last-offset]=arr[j][last];
                arr[j][last]=top;
                offset++;
            }
        }
    }
}


import java.util.*;
public class Main {
	static boolean check(char arr[][],char arr1[][],int n){
		for (int i=0;i<n;i++){
			for (int j=0;j<n;j++){
				if (arr[i][j] != arr1[i][j]){
					return false;
				}
			}
		}
		return true;
	}
	static char[][] flipy(char arr[][],int n){
		char[][]temp=new char[100][100];
		int j1 = n-1;
		for (int i=0;i<n;i++){
			int i1 = 0;
			for (int j=0;j<n;j++){
				temp[j][i] = arr[i1][j1];
				i1++;
			}
			j1--;
		}
		return temp;
	}
	static char[][] flipx(char arr[][],int n){
		char[][]temp=new char[100][100];
		int i1 = n-1;
		for (int i=0;i<n;i++){
			int j1 = 0;
			for (int j=0;j<n;j++){
				temp[i][j] = arr[i1][j1];
				j1++;
			}
			i1--;
		}
		return temp;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner s=new Scanner(System.in);
		int n=s.nextInt();
		char[][] arr=new char[100][100];
		char[][] arr1=new char[100][100];
		char[][] arr2=new char[100][100];
		for(int i=0;i<n;i++) {
			String temp=s.next();
			for(int j=0;j<n;j++) {
				arr[i][j]=temp.charAt(j);
			}
		}
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				arr1[i][j]=arr[j][i];
			}
		}
		for(int i=0;i<n;i++) {
			String temp=s.next();
			for(int j=0;j<n;j++) {
				arr2[i][j]=temp.charAt(j);
			}
		}

		for(int i=0;i<50;i++) {
			char[][] temp=new char[100][100];
			temp=arr;
			for(int j=0;j<50;j++) {
				int a=i;
				int b=j;
				while(a!=0) {
					temp=flipx(temp,n);
					a--;
				}

				while(b!=0) {
					temp=flipy(temp,n);
					b--;
				}
				if(check(temp,arr2,n)) {
					System.out.println("Yes");
					return;
				}
			}

		}

		for(int i=0;i<50;i++) {
			char[][] temp=new char[100][100];
			temp=arr1;
			for(int j=0;j<50;j++) {
				int a=i;
				int b=j;
				while(a!=0) {
					temp=flipx(temp,n);
					a--;
					//System.out.println("hello");
				}
				while(b!=0) {
					temp=flipy(temp,n);
					b--;
				}
				if(check(temp,arr2,n)) {
					System.out.println("Yes");
					return;
				}
			}

		}
		System.out.println("No");
	}

}


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Created by Administrator on 2018/2/22.
 */
public class CF915E {
    static final boolean IS_OJ = System.getProperty("ONLINE_JUDGE") != null;
    public static BlockReader input;

    public static void main(String[] args) throws FileNotFoundException {
        if (!IS_OJ) {
            System.setIn(new FileInputStream("D:\\DataBase\\TESTCASE\\codeforces\\CF915E.in"));
        }
        input = new BlockReader(System.in);

        solve();
    }

    public static void solve() {
        int n = input.nextInteger();
        int q = input.nextInteger();
        BinTree tree = new BinTree(1, n);

        StringBuilder buffer = new StringBuilder();
        for (int i = 1; i <= q; i++) {

            int l = input.nextInteger();
            int r = input.nextInteger();
            int k = input.nextInteger();
            tree.set(l, r, k);
            int sum = tree.sumOf(1, n);
            buffer.append(sum).append('\n');
        }

        System.out.print(buffer);
    }

    public static class BinTree {
        Node root;
        int left, right;

        public BinTree(int l, int r) {
            root = new Node();
            root.setDirty(2, l, r);
            this.left = l;
            this.right = r;
        }

        public void set(int f, int t, int dirty) {
            set(f, t, dirty, left, right, root);
        }

        public int sumOf(int f, int t) {
            return sumOf(f, t, left, right, root);
        }

        public int sumOf(int f, int t, int l, int r, Node node) {
            if (f <= l && t >= r) {
                return node.sum;
            }

            node.ensureChildren(l, r);
            node.pushDown(l, r);
            int mid = (l + r) >> 1;
            int sum = 0;
            if (mid >= f) {
                sum += sumOf(f, t, l, mid, node.left);
            }
            if (t > mid) {
                sum += sumOf(f, t, mid + 1, r, node.right);
            }
            return sum;
        }

        private void set(int f, int t, int dirty, int l, int r, Node node) {
            if (f <= l && t >= r) {
                node.setDirty(dirty, l, r);
                return;
            }
            int mid = (l + r) >> 1;
            node.ensureChildren(l, r);
            node.pushDown(l, r);
            if (mid >= f) {
                set(f, t, dirty, l, mid, node.left);
            }
            if (mid < t) {
                set(f, t, dirty, mid + 1, r, node.right);
            }
            node.pushUp(l, r);
        }

        public static class Node {
            Node left;
            Node right;
            int sum;
            int dirty;

            public void ensureChildren(int l, int r) {
                if (left == null) {
                    left = new Node();
                    right = new Node();
                }
            }

            public void pushUp(int l, int r) {
                sum = left.sum + right.sum;
            }

            public void pushDown(int l, int r) {
                if(dirty != 0) {
                    int mid = (l + r) >> 1;
                    left.setDirty(dirty, l, mid);
                    right.setDirty(dirty, mid + 1, r);
                    dirty = 0;
                }
            }

            public void setDirty(int dirty, int l, int r) {
                this.dirty = dirty;
                if (dirty == 1) {
                    sum = 0;
                } else {
                    sum = r - l + 1;
                }
            }
        }
    }

    public static class BlockReader {
        static final int EOF = -1;
        InputStream is;
        byte[] dBuf;
        int dPos, dSize, next;
        StringBuilder builder = new StringBuilder();

        public BlockReader(InputStream is) {
            this(is, 4096);
        }

        public BlockReader(InputStream is, int bufSize) {
            this.is = is;
            dBuf = new byte[bufSize];
            next = nextByte();
        }

        public void skipBlank() {
            while (Character.isWhitespace(next)) {
                next = nextByte();
            }
        }

        public String nextBlock() {
            builder.setLength(0);
            skipBlank();
            while (next != EOF && !Character.isWhitespace(next)) {
                builder.append((char) next);
                next = nextByte();
            }
            return builder.toString();
        }

        public int nextInteger() {
            skipBlank();
            int ret = 0;
            boolean rev = false;
            if (next == '+' || next == '-') {
                rev = next == '-';
                next = nextByte();
            }
            while (next >= '0' && next <= '9') {
                ret = (ret << 3) + (ret << 1) + next - '0';
                next = nextByte();
            }
            return rev ? -ret : ret;
        }

        public int nextBlock(char[] data, int offset) {
            skipBlank();
            int index = offset;
            int bound = data.length;
            while (next != EOF && index < bound && !Character.isWhitespace(next)) {
                data[index++] = (char) next;
                next = nextByte();
            }
            return index - offset;
        }

        public boolean hasMore() {
            skipBlank();
            return next != EOF;
        }

        public int nextByte() {
            while (dPos >= dSize) {
                if (dSize == -1) {
                    return EOF;
                }
                dPos = 0;
                try {
                    dSize = is.read(dBuf);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return dBuf[dPos++];
        }
    }
}


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

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

  static class TaskG {
    SvLogger logger = new SvLogger().setPrintTimeEllapsed(true);
    final int MOD = 1_000_000_007;
    int n;
    int k;
    byte[] moebius;
    int[] powN;
    int[] val;
    long bi;

    void update(int i, int g) {
      if (moebius[g] == 0) {
        return;
      }
      bi = (bi - val[g] + MOD) % MOD;
      val[g] = moebius[g] * powN[i / g];
      bi = (bi + val[g] + MOD) % MOD;
    }

    public static IntList calcPrimeFactorizationOf(int n) {
      if (n < 0) {
        throw new IllegalArgumentException();
      }
      IntList factors = new IntArrayList();
      if (n == 0) {
        return factors;
      }

      if (n % 2 == 0) {
        n /= 2;
        while (n % 2 == 0) {
          n /= 2;
        }
        factors.add(2);
      }

      int maxFactor = (int) Math.sqrt(n);
      for (int factor = 3; factor <= maxFactor && n > 1; factor += 2) {
        if (n % factor == 0) {
          n /= factor;
          while (n % factor == 0) {
            n /= factor;
          }
          factors.add(factor);
          maxFactor = (int) Math.sqrt(n);
        }
      }

      if (n > 1) {
        factors.add(n);
      }

      return factors;
    }

    public void solve(int testNumber, InputStreamReader in, PrintWriter out) {
      SvScanner sc = new SvScanner(in);
      n = sc.nextInt();
      k = sc.nextInt();

      moebius = SvNumberTheoryUtils.genMoebiusFuncForIntsUpTo(k);
      val = new int[k + 1];

      powN = new int[k + 1];
      for (int i = 1; i <= k; ++i) {
        powN[i] = SvCommonMathUtils.pow(i, n, MOD);
      }

//    IntList[] primeDivsOf = genListsOfPrimeDivisorsForIntsUpTo(k);
//    logger.p("lists genareted");

      bi = 0;
      long ans = 0;
      for (int i = 1; i <= k; ++i) {
        // The next value of bi is computed using the previous, by updating
        // only the values g such that g divides i.
//      SvPrimalityUtils.IntPrimeFactor[] fact = SvPrimalityUtils.calcPrimeFactorizationOf(i);
//      for (int bitmask = 0; bitmask < (1 << fact.length); ++bitmask) {
//        int g = 1;
//        for (int j = 0; j < fact.length; ++j) {
//          if (((bitmask >>> j) & 1) == 1) {
//            g *= fact[j].prime;
//          }
//        }
//        update(i, g);
//      }

//      for (int bitmask = 0; bitmask < (1 << primeDivsOf[i].size()); ++bitmask) {
//        int g = 1;
//        for (int j = primeDivsOf[i].size() - 1; j >= 0; --j) {
//          if (((bitmask >>> j) & 1) == 1) {
//            g *= primeDivsOf[i].get(j);
//          }
//        }
//        update(i, g);
//      }

        IntList fact = calcPrimeFactorizationOf(i);
        for (int bitmask = 0; bitmask < (1 << fact.size()); ++bitmask) {
          int g = 1;
          for (int j = fact.size() - 1; j >= 0; --j) {
            if (((bitmask >>> j) & 1) == 1) {
              g *= fact.get(j);
            }
          }
          update(i, g);
        }

        ans = (ans + (bi ^ i)) % MOD;
      }

      logger.p("loop done");

      out.println(ans);
    }

  }

  static class SvLogger {
    private static final String MESSAGE_PREFIX = "> ";
    private boolean enabled = true;
    private boolean printTimeEllapsed = false;
    private long startedTime = System.currentTimeMillis();

    public SvLogger setPrintTimeEllapsed(boolean printTimeEllapsed) {
      this.printTimeEllapsed = printTimeEllapsed;
      return this;
    }

    public void p(String format, Object... args) {
      if (!enabled) {
        return;
      }
      printMessage(String.format(format, args));
    }

    private void printMessage(String msg) {
      String formattedTime =
          printTimeEllapsed ? " (" + (System.currentTimeMillis() - startedTime) + " ms)" : "";
      System.out.println(MESSAGE_PREFIX + msg + formattedTime);
    }

  }

  static abstract class IntAbstractStream implements IntStream {

    public String toString() {
      StringBuilder builder = new StringBuilder();
      boolean first = true;
      for (IntIterator it = intIterator(); it.isValid(); it.advance()) {
        if (first) {
          first = false;
        } else {
          builder.append(' ');
        }
        builder.append(it.value());
      }
      return builder.toString();
    }

    public boolean equals(Object o) {
      if (!(o instanceof IntStream)) {
        return false;
      }
      IntStream c = (IntStream) o;
      IntIterator it = intIterator();
      IntIterator jt = c.intIterator();
      while (it.isValid() && jt.isValid()) {
        if (it.value() != jt.value()) {
          return false;
        }
        it.advance();
        jt.advance();
      }
      return !it.isValid() && !jt.isValid();
    }

    public int hashCode() {
      int result = 0;
      for (IntIterator it = intIterator(); it.isValid(); it.advance()) {
        result *= 31;
        result += it.value();
      }
      return result;
    }

  }

  static class SvNumberTheoryUtils {
    public static byte[] genMoebiusFuncForIntsUpTo(int n) {
      byte[] m = new byte[n + 1];
      for (int i = 1; i <= n; ++i) {
        m[i] = 1;
      }
      boolean[] isPr = SvPrimalityUtils.genBoolArrayForPrimalityTestUpTo(n);
      for (int p = 2; p <= n; ++p) {
        if (isPr[p]) {
          long p2 = (long) p * p;
          for (long j = p2; j <= n; j += p2) {
            m[(int) j] = 0;
          }
          for (int j = p; j <= n && j > 0; j += p) {
            m[j] = (byte) -m[j];
          }
        }
      }
      return m;
    }

  }

  static class SvPrimalityUtils {
    public static boolean[] genBoolArrayForPrimalityTestUpTo(int n) {
      if (n < 0) {
        throw new IllegalArgumentException();
      }
      boolean[] isPrime = new boolean[n + 1];
      Arrays.fill(isPrime, true);
      if (n >= 0) {
        isPrime[0] = false;
      }
      if (n >= 1) {
        isPrime[1] = false;
      }
      for (int i = 2; i <= n; ++i) {
        if (isPrime[i]) {
          for (long j = ((long) i) * i; j <= n; j += i) {
            isPrime[(int) j] = false;
          }
        }
      }
      return isPrime;
    }

  }

  static interface IntList extends IntReversableCollection {
    public abstract int get(int index);

    public abstract void addAt(int index, int value);

    public abstract void removeAt(int index);

    default public IntIterator intIterator() {
      return new IntIterator() {
        private int at;
        private boolean removed;

        public int value() {
          if (removed) {
            throw new IllegalStateException();
          }
          return get(at);
        }

        public boolean advance() {
          at++;
          removed = false;
          return isValid();
        }

        public boolean isValid() {
          return !removed && at < size();
        }

        public void remove() {
          removeAt(at);
          at--;
          removed = true;
        }
      };
    }

    default public void add(int value) {
      addAt(size(), value);
    }

  }

  static interface IntCollection extends IntStream {
    public int size();

    default public void add(int value) {
      throw new UnsupportedOperationException();
    }

    default public IntCollection addAll(IntStream values) {
      for (IntIterator it = values.intIterator(); it.isValid(); it.advance()) {
        add(it.value());
      }
      return this;
    }

  }

  static class SvScanner {
    private BufferedReader reader;
    private StringTokenizer tokenizer = new StringTokenizer("");

    public SvScanner(InputStreamReader in) {
      reader = new BufferedReader(in);
    }

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

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

  }

  static interface IntIterator {
    public int value() throws NoSuchElementException;

    public boolean advance();

    public boolean isValid();

  }

  static class InputReader {
    private InputStream stream;

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

  }

  static class IntArrayList extends IntAbstractStream implements IntList {
    private int size;
    private int[] data;

    public IntArrayList() {
      this(3);
    }

    public IntArrayList(int capacity) {
      data = new int[capacity];
    }

    public IntArrayList(IntCollection c) {
      this(c.size());
      addAll(c);
    }

    public IntArrayList(IntStream c) {
      this();
      if (c instanceof IntCollection) {
        ensureCapacity(((IntCollection) c).size());
      }
      addAll(c);
    }

    public IntArrayList(IntArrayList c) {
      size = c.size();
      data = c.data.clone();
    }

    public IntArrayList(int[] arr) {
      size = arr.length;
      data = arr.clone();
    }

    public int size() {
      return size;
    }

    public int get(int at) {
      if (at >= size) {
        throw new IndexOutOfBoundsException("at = " + at + ", size = " + size);
      }
      return data[at];
    }

    private void ensureCapacity(int capacity) {
      if (data.length >= capacity) {
        return;
      }
      capacity = Math.max(2 * data.length, capacity);
      data = Arrays.copyOf(data, capacity);
    }

    public void addAt(int index, int value) {
      ensureCapacity(size + 1);
      if (index > size || index < 0) {
        throw new IndexOutOfBoundsException("at = " + index + ", size = " + size);
      }
      if (index != size) {
        System.arraycopy(data, index, data, index + 1, size - index);
      }
      data[index] = value;
      size++;
    }

    public void removeAt(int index) {
      if (index >= size || index < 0) {
        throw new IndexOutOfBoundsException("at = " + index + ", size = " + size);
      }
      if (index != size - 1) {
        System.arraycopy(data, index + 1, data, index, size - index - 1);
      }
      size--;
    }

  }

  static interface IntReversableCollection extends IntCollection {
  }

  static interface IntStream extends Iterable<Integer>, Comparable<IntStream> {
    public IntIterator intIterator();

    default public Iterator<Integer> iterator() {
      return new Iterator<Integer>() {
        private IntIterator it = intIterator();

        public boolean hasNext() {
          return it.isValid();
        }

        public Integer next() {
          int result = it.value();
          it.advance();
          return result;
        }
      };
    }

    default public int compareTo(IntStream c) {
      IntIterator it = intIterator();
      IntIterator jt = c.intIterator();
      while (it.isValid() && jt.isValid()) {
        int i = it.value();
        int j = jt.value();
        if (i < j) {
          return -1;
        } else if (i > j) {
          return 1;
        }
        it.advance();
        jt.advance();
      }
      if (it.isValid()) {
        return 1;
      }
      if (jt.isValid()) {
        return -1;
      }
      return 0;
    }

  }

  static class SvCommonMathUtils {
    public static int pow(int n, long deg, int mod) {
      if (n < 0 || deg < 0 || mod <= 0) {
        throw new IllegalArgumentException();
      }
      if (deg == 0) {
        return 1;
      } else if (deg % 2 == 0) {
        long tmp = pow(n, deg / 2, mod);
        return (int) ((tmp * tmp) % mod);
      } else {
        return (int) (((n % mod) * (long) pow(n, deg - 1, mod)) % mod);
      }
    }

  }
}


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

public class tr1 {
	static PrintWriter out;
	static StringBuilder sb;
	static int n, z, k;
	static long mod = (long) 1e9 + 7;
	static int[][] memo;
	static String s;
	static int[][] ad;
	static TreeMap<Long, Integer>[] gs;
	static long inf = Long.MAX_VALUE;
	static int[] color;
	static ArrayList<Integer> o;
	static char[][] g;
	static boolean[] vis, vis1;
	static long[] f;
	static int[] a;
	static int lj;
	static int[][] mat;

	public static void main(String[] args) throws Exception {
		Scanner sc = new Scanner(System.in);
		out = new PrintWriter(System.out);
		n = sc.nextInt();
		k = sc.nextInt();
		long ans = 0;
		long sum = 0;
		long[] ar = new long[k + 1];
		for (int i = 1; i <= k; i++) {
			long total = modPow(i, n) - modPow(i - 1, n);
			ar[i] += total;
			ar[i] %= mod;
			ar[i] += mod;
			ar[i] %= mod;
			sum += ar[i];
			ans = ans + (sum ^ i);
			for (int j = i + i; j <= k; j += i) {
				ar[j] -= ar[i];
			}
		}
		System.out.println(ans%mod);
		out.flush();
	}

	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 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 int[] nextArrInt(int n) throws IOException {
			int[] a = new int[n];
			for (int i = 0; i < n; i++)
				a[i] = nextInt();
			return a;
		}

		public long[] nextArrLong(int n) throws IOException {
			long[] a = new long[n];
			for (int i = 0; i < n; i++)
				a[i] = nextLong();
			return a;
		}

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

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


/* Author: Ronak Agarwal */
import java.io.* ; import java.util.* ; import java.math.* ;
import static java.lang.Math.min ;
import static java.lang.Math.max ;
import static java.lang.Math.abs ;
import static java.lang.Math.log ;
import static java.lang.Math.pow ;
import static java.lang.Math.sqrt ;
/* Thread is created here to increase the stack size of the java code so that recursive dfs can be performed */
public class Codeshefcode{
	public static void main(String[] args) throws IOException{
		new Thread(null,new Runnable(){	public void run(){ exec_Code() ;} },"Solver",1l<<27).start() ;
	}
	static void exec_Code(){
		try{
			Solver Machine = new Solver() ;
			Machine.Solve() ; Machine.Finish() ;}
		catch(Exception e){ e.printStackTrace() ; print_and_exit() ;}
		catch(Error e){ e.printStackTrace() ; print_and_exit() ; }
	}
	static void print_and_exit(){ System.out.flush() ; System.exit(-1) ;}
}
class Reader{
	BufferedReader reader;
	StringTokenizer tkz;
	Reader(InputStream input) {
		reader = new BufferedReader(new InputStreamReader(input)) ;
		tkz = new StringTokenizer("") ;
	}
	String s() throws IOException{
		while (!tkz.hasMoreTokens()) tkz = new StringTokenizer(reader.readLine()) ;
		return tkz.nextToken() ;
	}
	int i() throws IOException{ return Integer.parseInt(s()) ;}
	long l() throws IOException{ return Long.parseLong(s()) ;}
	double d() throws IOException{	return Double.parseDouble(s()) ;}
}
/* All the useful functions,constants,renamings are here*/
class Template{
	/* Constants Section */
	final int INT_MIN = Integer.MIN_VALUE ; final int INT_MAX = Integer.MAX_VALUE ;
	final long LONG_MIN = Long.MIN_VALUE ; final long LONG_MAX = Long.MAX_VALUE ;
	static long MOD = 1000000007 ;
	static Reader ip = new Reader(System.in) ;
	static PrintWriter op = new PrintWriter(System.out) ;
	/* Methods for writing */
	static void p(Object o){ op.print(o) ; }
	static void pln(Object o){ op.println(o) ;}
	static void Finish(){ op.flush();	op.close(); }
	/* Implementation of operations modulo MOD */
	static long inv(long a){ return powM(a,MOD-2) ; }
	static long m(long a,long b){ return (a*b)%MOD ; }
	static long d(long a,long b){ return (a*inv(b))%MOD ; }
	static long powM(long a,long b){
		if(b<0) return powM(inv(a),-b) ;
		long val=a ; long ans=1 ;
		while(b!=0){
			if((b&1)==1) ans = (ans*val)%MOD ;
			val = (val*val)%MOD ;
			b/=2 ;
		}
		return ans ;
	}
	/* Renaming of some generic utility classes */
	final static class mylist extends ArrayList<Integer>{}
	final static class mylisti extends ArrayList<Integer>{}
	final static class myset extends TreeSet<Long>{}
	final static class mystack extends Stack<Integer>{}
	final static class mymap extends TreeMap<Long,Integer>{}
}
/* Implementation of the pair class, useful for every other problem */
class pair implements Comparable<pair>{
	int x ; int y ; int id ;
	pair(int _x,int _y,int _id){ x=_x ; y=_y ; id=_id ;}
	public int compareTo(pair p){
		return (this.x<p.x ? -1 : (this.x>p.x ? 1 : (this.y<p.y ? -1 : (this.y>p.y ? 1 : 0)))) ;
	}
}
/* Main code starts here */
class Solver extends Template{
	int n,k ;
	int LIM = 2000000 ;
	long pn[] = new long[LIM+1] ;
	int u[] = new int[LIM+1] ;
	int fac[] = new int[LIM+1] ;
	mylist div[] = new mylist[LIM+1] ;
	void preComp(){
		for(int i=1 ; i<=LIM ; i++){
			div[i] = new mylist() ;
			div[i].add(1) ;
		}
		for(int i=1 ; i<=LIM ; i++) pn[i] = powM(i,n) ;
		for(int i=2 ; i<=LIM ; i++)
			if(fac[i]==0)
				for(int j=i ; j<=LIM ; j+=i){
					fac[j] = i ;
					div[j].add(i) ;
				}
		u[1] = 1 ;
		for(int i=2 ; i<=LIM ; i++){
			int prm = fac[i] ;
			int j = i/prm ;
			u[i] = (j%prm==0 ? 0 : -u[j]) ;
		}
	}
	public void Solve() throws IOException{
		n = ip.i() ; k = ip.i() ;
		preComp() ;

	}
}


import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
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 Egor Kulikov (egor@egork.net)
 */
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 long MOD = (long) (1e9 + 7);

	public void solve(int testNumber, InputReader in, OutputWriter out) {
		long width = in.readInt();
		long evenWidth = (width + 2) / 2;
		long oddWidth = (width + 1) / 2;
		long height = in.readInt();
		long evenHeight = (height + 2) / 2;
		long oddHeight = (height + 1) / 2;
		long total = 0;
		int[][] gcd = new int[(int) (width + 1)][(int) (height + 1)];
		for (int i = 0; i <= width; i++)
			gcd[i][0] = i + 1;
		for (int i = 0; i <= height; i++)
			gcd[0][i] = i + 1;
		for (int i = 1; i <= width; i++) {
			for (int j = 1; j <= height; j++) {
				if (i >= j)
					gcd[i][j] = gcd[i - j][j];
				else
					gcd[i][j] = gcd[i][j - i];
			}
		}
		for (int i = 0; i <= width; i++) {
			long remainingWidth = width - i + 1;
			for (int j = 0; j <= height; j++) {
				long remainingHeight = height - j + 1;
				long current;
				if ((i & 1) == 0) {
					if ((j & 1) == 0)
						current = (width + 1) * (height + 1) * remainingWidth * remainingHeight;
					else
						current = evenWidth * (height + 1) * ((remainingWidth + 1) >> 1) * remainingHeight + oddWidth * (height + 1) * (remainingWidth >> 1) * remainingHeight;
				} else {
					if ((j & 1) == 0)
						current = evenHeight * (width + 1) * ((remainingHeight + 1) >> 1) * remainingWidth + oddHeight * (width + 1) * (remainingHeight >> 1) * remainingWidth;
					else {
						current = (((height + 1) * (width + 1) + 1) >> 1) * ((remainingHeight * remainingWidth + 1) >> 1) +
							(((height + 1) * (width + 1)) >> 1) * ((remainingHeight * remainingWidth) >> 1);
					}
				}
				if (i != 0)
					current <<= 1;
				if (j != 0)
					current <<= 1;
				long currentMinus = 0;
				if (gcd[i][j] > 2)
					currentMinus += 6 * (gcd[i][j] - 2) * (width - i + 1) * (height - j + 1);
				if (gcd[i][j] > 1)
					currentMinus += 6 * (width - i + 1) * (height - j + 1);
				if (i != 0 && j != 0)
					currentMinus <<= 1;
				if (i == 0 && j == 0)
					currentMinus += (width + 1) * (height + 1);
				current -= currentMinus;
				total += current;
			}
			total %= MOD;
		}
		if (total < 0)
			total += MOD;
		out.printLine(total);
	}
}

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

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

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

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

	}


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

public class D {

	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;
	boolean eof;

	static final int MOD = 1000000007;

	int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}

	void solve() throws IOException {
		int w = nextInt();
		int h = nextInt();

		int[] x = { w / 2 + 1, (w + 1) / 2 };
		int[] y = { h / 2 + 1, (h + 1) / 2 };
		int[][] c = new int[2][2];
		for (int i = 0; i < 2; i++)
			for (int j = 0; j < 2; j++)
				c[i][j] = x[i] * y[j];

		int ans = 0;

		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++)
						for (int x3 = 0; x3 < 2; x3++)
							for (int y3 = 0; y3 < 2; y3++) {

								int sq = (x1 * y2 - x2 * y1)
										+ (x2 * y3 - x3 * y2)
										+ (x3 * y1 - x1 * y3);
								if ((sq & 1) == 1)
									continue;
								ans += (int) ((long) c[x1][y1] * c[x2][y2]
										% MOD * c[x3][y3] % MOD);
								if (ans >= MOD)
									ans -= MOD;

							}

		for (int dx = 0; dx <= w; dx++)
			for (int dy = 0; dy <= h; dy++) {
				int mult = (w - dx + 1) * (h - dy + 1);
				if (dx == 0 && dy == 0) {
					ans -= mult;
					if (ans < 0)
						ans += MOD;
					continue;
				}
				if (dx != 0 && dy != 0)
					mult <<= 1;
				int all = gcd(dx, dy) * 6;

				ans -= (int)((long)mult * all % MOD);
				if (ans < 0)
					ans += MOD;
			}

		out.println(ans);

	}

	void inp() throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		solve();
		out.close();
	}

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

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (Exception e) {
				eof = true;
				return null;
			}
		}
		return st.nextToken();
	}

	String nextString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			eof = true;
			return null;
		}
	}

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

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

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


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

public class Solution {

	private StringTokenizer st;
	private BufferedReader in;
	private PrintWriter out;

	final long mod = 1000000007;

	long st(long x, long y) {
		return (x + mod - (y % mod)) % mod;
	}

	int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}

	public void solve() throws IOException {
		int w = nextInt();
		int h = nextInt();
		long ans = 0;
		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) {
				for (int x3 = 0; x3 < 2; ++x3) {
				for (int y3 = 0; y3 < 2; ++y3) {
					if (((x1 + x2 + x3) * (y1 + y2 + y3) - (x1 * y1 + x2 * y2 + x3 * y3)) % 2 == 0) {
						long val = 1;
						val = (val * ((w + 2 - x1) / 2)) % mod;
						val = (val * ((w + 2 - x2) / 2)) % mod;
						val = (val * ((w + 2 - x3) / 2)) % mod;
						val = (val * ((h + 2 - y1) / 2)) % mod;
						val = (val * ((h + 2 - y2) / 2)) % mod;
						val = (val * ((h + 2 - y3) / 2)) % mod;
						ans = (ans + val) % mod;
					}
				}
				}
			}
			}
		}
		}
		long total = ((w + 1) * (h + 1)) % mod;
		ans = st(ans, total);
		ans = st(ans, total * (total - 1) * 3);
		for (int x = 0; x <= w; ++x) {
			for (int y = 0; y <= h; ++y) {
				if (gcd(x, y) != 1) {
					continue;
				}
				long st = 0;
				for (int u = 1; x * u <= w && y * u <= h; ++u) {
					for (int v = u + 1; x * v <= w && y * v <= h; ++v) {
						st += (w - x * v + 1) * (h - y * v + 1);
					}
				}
				st *= x == 0 || y == 0 ? 6 : 12;
				ans = st(ans, st);
			}
		}
		out.println(ans);
	}

	public void run() throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		eat("");

		solve();

		out.close();
	}

	void eat(String s) {
		st = new StringTokenizer(s);
	}

	String next() throws IOException {
		while (!st.hasMoreTokens()) {
			String line = in.readLine();
			if (line == null) {
				return null;
			}
			eat(line);
		}
		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());
	}

	public static void main(String[] args) throws IOException {
		Locale.setDefault(Locale.US);
		new Solution().run();
	}

}


import java.util.List;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Locale;
import java.util.ArrayList;
import java.util.Comparator;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.math.BigInteger;
import java.io.InputStream;

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

class TaskD_LittleElAndTriangle {
    public static final int MOD = (int) 1e9 + 7;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int m = in.nextInt();

        int res = 0;
        int amY0 = getAm(false, 0, m);
        int amY1 = m + 1 - amY0;
        int amX0 = getAm(false, 0, n);
        int amX1 = n + 1 - amX0;

        for (int x = 0; x <= 1; ++x) {
            int B1 = BitUtils.checkBit(1 - x, 0) ? amX1 : amX0;
            int B3 = BitUtils.checkBit(x, 0) ? amX1 : amX0;
            int amX = (x == 0 ? (n/2) + 1 : (n +1) / 2);

            for (int y = 0; y <= 1; ++y) {
                int amY = (y == 0 ? (m/2) + 1 : (m +1) / 2);
                int B2 = BitUtils.checkBit(y, 0) ? amY1 : amY0;
                int B4 = BitUtils.checkBit(1 - y, 0) ? amY1 : amY0;
                for (int xx2 = 0; xx2 <= 1; ++xx2) {
                    int A1 = BitUtils.checkBit(xx2, 0) ? amX1 : amX0;
                    for (int yy1 = 0; yy1 <= 1; ++yy1) {
                        if (odd(xx2 - x) * odd(yy1 - y) == 0) {
                            int A2 = BitUtils.checkBit(yy1, 0) ? amY1 : amY0;
                            long cur2 = (B1 * B2 + B3 * (m+1));
                            cur2 = cur2 * A1 * A2;
                            cur2 %= MOD;
                            cur2 *= amX;
                            cur2 %= MOD;
                            cur2 *= amY;
                            cur2 %= MOD;
                            res += cur2;
                            if (res >= MOD) res -= MOD;
                        } else {
                            int A2 = BitUtils.checkBit(yy1, 0) ? amY1 : amY0;
                            long cur = A1 * A2;
                            cur = cur * B1 * B4;
                            cur %= MOD;
                            cur *= amX;
                            cur %= MOD;
                            cur *= amY;
                            cur %= MOD;
                            res += cur;
                            if (res >= MOD) res -= MOD;
                        }
                    }
                }
            }
        }

        for (int dx = 0; dx <= n; ++dx) {
            for (int dy = 0; dy <= m; ++dy) {
                if (dx == 0 && dy == 0) continue;
                int amX = n - dx + 1;
                int amY = m - dy + 1;
                int amPoints = IntegerUtils.gcd(dx, dy);
                if (dx == 0 || dy == 0) {
                    res -= (amPoints * 6L * amX * amY) % MOD;
                } else {
                    res -= (amPoints * 12L * amX * amY) % MOD;
                }
                res += MOD;
                if (res >= MOD) {
                    res -= MOD;
                }
            }
        }

        res -= (n + 1) * (m + 1);
        res += MOD;
        if (res >= MOD) {
            res -= MOD;
        }

        out.println(res);
    }

    private int odd(int x) {
        return BitUtils.checkBit(x, 0) ? 1 : 0;
    }

    private int getAm(boolean odd, int begin, int end) {
        if (BitUtils.checkBit(begin, 0) != odd) {
            ++begin;
        }
        if (BitUtils.checkBit(end, 0) != odd) {
            --end;
        }
        if (begin <= end) {
            return (end - begin) / 2 + 1;
        }
        return 0;
    }
}

class InputReader {
    private BufferedReader reader;
    private StringTokenizer stt;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
    }

    public String nextLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            return null;
        }
    }

    public String nextString() {
        while (stt == null || !stt.hasMoreTokens()) {
            stt = new StringTokenizer(nextLine());
        }
        return stt.nextToken();
    }

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

}

class BitUtils {
    public static boolean checkBit(int mask, int bit) {
        return (mask & (1 << bit)) > 0;
    }

}

class IntegerUtils {

    public static int gcd(int x, int y) {
        return y == 0 ? x : gcd(y, x % y);
    }

}


import java.awt.Point;
import java.util.Scanner;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Phantom
 */
public class T4 {

    public static int orientation(Point p, Point q, Point r) {
        double val = (q.getY() - p.getY()) * (r.getX() - q.getX())
                - (q.getX() - p.getX()) * (r.getY() - q.getY());

        if (val == 0.0) {
            return 0; // colinear
        }
        return (val > 0) ? 1 : 2; // clock or counterclock wise
    }

    public static boolean intersect(Point p1, Point q1, Point p2, Point q2) {

        int o1 = orientation(p1, q1, p2);
        int o2 = orientation(p1, q1, q2);
        int o3 = orientation(p2, q2, p1);
        int o4 = orientation(p2, q2, q1);

        if (o1 != o2 && o3 != o4) {
            return true;
        }

        return false;
    }

    static boolean intersects(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
        float bx = x2 - x1;
        float by = y2 - y1;
        float dx = x4 - x3;
        float dy = y4 - y3;
        float b_dot_d_perp = bx * dy - by * dx;
        if (b_dot_d_perp == 0) {
            return false;
        }
        float cx = x3 - x1;
        float cy = y3 - y1;
        float t = (cx * dy - cy * dx) / b_dot_d_perp;
        if (t < 0 || t > 1) {
            return false;
        }
        float u = (cx * by - cy * bx) / b_dot_d_perp;
        if (u < 0 || u > 1) {
            return false;
        }
        return true;
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        int m = input.nextInt();
        Point[] rebel = new Point[n];
        Point[] base = new Point[m];
        for (int i = 0; i < n; i++) {
            rebel[i] = new Point(input.nextInt(), input.nextInt());
        }
        for (int i = 0; i < m; i++) {
            base[i] = new Point(input.nextInt(), input.nextInt());
        }
        if (m != n) {
            System.out.println("NO");
        } else {
            boolean valid = true;
            for (int i = 0; i < n - 1; i++) {
                for (int j = i + 1; j < m; j++) {

                    if (intersects(rebel[i].x,rebel[i].y,base[i].x,base[i].y,rebel[j].x,rebel[j].y,base[j].x,base[j].y)) {
                        valid = false;
                        break;
                    }
                }
            }
            if (valid) {
                System.out.println("YES");
            } else {
                System.out.println("NO");
            }
        }
    }
}


import java.util.Iterator;
import java.util.LinkedList;
import java.util.Scanner;
import java.lang.Math;

public class GuardDuty {

	boolean segmentosSeInterceptam(Ponto p1, Ponto p2, Ponto p3, Ponto p4) {

		int d1 = direcao(p3, p4, p1);
		int d2 = direcao(p3, p4, p2);
		int d3 = direcao(p1, p2, p3);
		int d4 = direcao(p1, p2, p4);

		if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) {
			return true;
		} else if (d1 == 0 && noSegmento(p3, p4, p1)) {
			return true;
		} else if (d2 == 0 && noSegmento(p3, p4, p2)) {
			return true;
		} else if (d3 == 0 && noSegmento(p1, p2, p3)) {
			return true;
		} else if (d4 == 0 && noSegmento(p1, p2, p4)) {
			return true;
		} else {
			return false;
		}
	}

	int direcao(Ponto pi, Ponto pj, Ponto pk) {
		int resp = (pk.x - pi.x) * (pj.y - pi.y) - (pj.x - pi.x) * (pk.y - pi.y);
		// (pk - pi) * (pj - pi)
		return resp;
	}

	boolean noSegmento(Ponto pi, Ponto pj, Ponto pk) {
		if ((Math.min(pi.x, pj.x) <= pk.x) && (pk.x <= Math.max(pi.x, pj.x))) {
			if ((Math.min(pi.y, pj.y) <= pk.y) && (pk.y <= Math.max(pi.y, pj.y))) {
				return true;
			}
		}
		return false;
	}

	boolean nSegmentosInterceptam(Ponto[] s) {
		// T = NULL;
		LinkedList<Integer> ll = new LinkedList<Integer>();
		ll.clear();
		Iterator<Integer> it = ll.iterator();
		int ant = -1;
		ordenaExtremidades(s);
		for (int p = 0; p < s.length; p++) {
			if (s[p].esq) {

				ll.add(s[p].seg);
				it = ll.iterator();
				ant = -1;

				// Percorre pra saber se existe segmentos acima ou abaixo do
				// atual na estrutura aux
				while (it.hasNext()) {
					Iterator<Integer> temp = it;
					int next = temp.next();
					//System.out.println("next = " + next);
					if (next == s[p].seg) {

						// Se existe segmento acima e eles se interceptam em
						// algum ponto
						if (temp.hasNext()) {

							int seg2 = temp.next();

							//System.out.println("1x = " + s[p].x + ", y = " + s[p].y + ", p = " + p);

							Ponto fim1 = buscaPonto(s, p, s[p].seg, false);
							Ponto ini2 = buscaPonto(s, 0, seg2, true);
							Ponto fim2 = buscaPonto(s, p, seg2, false);

							if (fim1 != null && ini2 != null && fim2 != null) {

								if (segmentosSeInterceptam(s[p], fim1, ini2, fim2)) {
									return true;
								}
							}
						}

						// Se existe segmento abaixo e eles se interceptam em
						// algum ponto
						if (ant != -1) {
							// temp = ant;
							int segAnt = ant;

							//System.out.println("2x = " + s[p].x + ", y = " + s[p].y + ", p = " + p);

							Ponto iniAnt = buscaPonto(s, 0, segAnt, true);
							Ponto fimAnt = buscaPonto(s, p, segAnt, false);
							Ponto fim1 = buscaPonto(s, p, s[p].seg, false);

							if (fim1 != null && iniAnt != null && fimAnt != null) {
								if (segmentosSeInterceptam(iniAnt, fimAnt, s[p], fim1)) {
									return true;
								}
							}

						}

					}

					ant = next;
				}
			} else if (!s[p].esq) {

				it = ll.iterator();
				ant = -1;

				while (it.hasNext()) {

					Iterator<Integer> temp = it;
					int next = temp.next();
					//System.out.println("next = " + next);
					if (next == s[p].seg) {

						// Se existe um segmento acima e outro abaixo do atual
						if ((ant != -1)) {

							int seg2 = next;

							//System.out.println("3x = " + s[p].x + ", y = " + s[p].y + ", p = " + p);

							Ponto ini2 = buscaPonto(s, 0, seg2, true);
							Ponto fim2 = buscaPonto(s, p, seg2, false);

							// Iterator<Integer> temp2 = ant;
							int segAnt = ant;
							Ponto iniAnt = buscaPonto(s, 0, segAnt, true);
							Ponto fimAnt = buscaPonto(s, p, segAnt, false);

							if (fimAnt != null && ini2 != null && fim2 != null && iniAnt != null && segAnt != seg2) {
								if (segmentosSeInterceptam(ini2, fim2, iniAnt, fimAnt)) {
									return true;
								}
							}
						}

					}

					ant = next;
				}
				Integer rem = s[p].seg;
				ll.remove(rem);

			}

		}
		return false;
	}

	Ponto buscaPonto(Ponto[] s, int ini, int seg, boolean esq) {
		for (int i = ini; ini < s.length; i++) {
			if (s[i].seg == seg && s[i].esq == esq) {
				return s[i];
			}
		}
		return null;
	}

	void ordenaExtremidades(Ponto[] s) {

		for (int i = 1; i < s.length; i++) {

			Ponto v = s[i];
			int j = i;

			while ((j > 0)) {
				if (s[j - 1].x > v.x) {
					s[j] = s[j - 1];
					j--;
				} else if (s[j - 1].x == v.x) {
					if (!s[j - 1].esq && v.esq) {
						s[j] = s[j - 1];
						j--;
					} else if (s[j - 1].esq == v.esq) {
						if (s[j - 1].y > v.y) {
							s[j] = s[j - 1];
							j--;
						} else {
							break;
						}
					} else {
						break;
					}
				} else {
					break;
				}
			}
			s[j] = v;

		}
	}

	public static void main(String[] args) {

		GuardDuty gd = new GuardDuty();
		Scanner in = new Scanner(System.in);

		int r = in.nextInt();
		int b = in.nextInt();

		if (r != b) {
			System.out.println("No");
			in.close();
			//System.exit(0);
			return;
		}

		Ponto[] navesBases = new Ponto[r + b];

		int x, y;
		// Naves na primeira metade
		for (int i = 0; i < r; i++) {

			x = in.nextInt();
			y = in.nextInt();

			navesBases[i] = new Ponto(x, y, true);
		}

		// Bases na segunda metade
		for (int j = r; j < navesBases.length; j++) {

			x = in.nextInt();
			y = in.nextInt();

			navesBases[j] = new Ponto(x, y, false);
		}

		for (int k = 0; k < r; k++) {
			for (int l = r; l < navesBases.length; l++) {
				navesBases[l].seg = l - r + 1;

				if (l + k - r < r) {
					navesBases[l + k - r].seg = l - r + 1;

					if (navesBases[l].x < navesBases[l + k - r].x) {
						navesBases[l].esq = true;
						navesBases[l + k - r].esq = false;
					} else {
						navesBases[l].esq = false;
						navesBases[l + k - r].esq = true;
					}

				} else {

					navesBases[l + k - 2 * r].seg = l - r + 1;
					if (navesBases[l].x < navesBases[l + k - 2 * r].x) {

						navesBases[l].esq = true;
						navesBases[l + k - 2 * r].esq = false;
					} else {
						navesBases[l].esq = false;
						navesBases[l + k - 2 * r].esq = true;
					}

				}

			}

			if(gd.nSegmentosInterceptam(navesBases)) {
				System.out.println("Yes");
				in.close();
				//System.exit(1);
				return;
			}
		}

		System.out.println("No");
		in.close();
		//System.exit(0);
		return;
	}

}

class Ponto {

	public int x;
	public int y;
	public int seg;
	public boolean esq;
	public boolean nave;

	public Ponto(int x, int y, boolean nave) {
		super();
		this.x = x;
		this.y = y;
		this.nave = nave;
	}

}


import java.util.Iterator;
import java.util.LinkedList;
import java.util.Scanner;
import java.lang.Math;

public class GuardDuty {

	boolean segmentosSeInterceptam(Ponto p1, Ponto p2, Ponto p3, Ponto p4) {

		int d1 = direcao(p3, p4, p1);
		int d2 = direcao(p3, p4, p2);
		int d3 = direcao(p1, p2, p3);
		int d4 = direcao(p1, p2, p4);

		if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) {
			return true;
		} else if (d1 == 0 && noSegmento(p3, p4, p1)) {
			return true;
		} else if (d2 == 0 && noSegmento(p3, p4, p2)) {
			return true;
		} else if (d3 == 0 && noSegmento(p1, p2, p3)) {
			return true;
		} else if (d4 == 0 && noSegmento(p1, p2, p4)) {
			return true;
		} else {
			return false;
		}
	}

	int direcao(Ponto pi, Ponto pj, Ponto pk) {
		int resp = (pk.x - pi.x) * (pj.y - pi.y) - (pj.x - pi.x) * (pk.y - pi.y);
		// (pk - pi) * (pj - pi)
		return resp;
	}

	boolean noSegmento(Ponto pi, Ponto pj, Ponto pk) {
		if ((Math.min(pi.x, pj.x) <= pk.x) && (pk.x <= Math.max(pi.x, pj.x))) {
			if ((Math.min(pi.y, pj.y) <= pk.y) && (pk.y <= Math.max(pi.y, pj.y))) {
				return true;
			}
		}
		return false;
	}

	boolean nSegmentosInterceptam(Ponto[] s) {
		// T = NULL;
		LinkedList<Integer> ll = new LinkedList<Integer>();
		ll.clear();
		Iterator<Integer> it = ll.iterator();
		int ant = -1;
		ordenaExtremidades(s);
		for (int p = 0; p < s.length; p++) {
			if (s[p].esq) {

				ll.add(s[p].seg);
				it = ll.iterator();
				ant = -1;

				// Percorre pra saber se existe segmentos acima ou abaixo do
				// atual na estrutura aux
				while (it.hasNext()) {
					Iterator<Integer> temp = it;
					int next = temp.next();
					//System.out.println("next = " + next);
					if (next == s[p].seg) {

						// Se existe segmento acima e eles se interceptam em
						// algum ponto
						if (temp.hasNext()) {

							int seg2 = temp.next();

							//System.out.println("1x = " + s[p].x + ", y = " + s[p].y + ", p = " + p);

							Ponto fim1 = buscaPonto(s, p, s[p].seg, false);
							Ponto ini2 = buscaPonto(s, 0, seg2, true);
							Ponto fim2 = buscaPonto(s, p, seg2, false);

							if (fim1 != null && ini2 != null && fim2 != null) {

								if (segmentosSeInterceptam(s[p], fim1, ini2, fim2)) {
									return true;
								}
							}
						}

						// Se existe segmento abaixo e eles se interceptam em
						// algum ponto
						if (ant != -1) {
							// temp = ant;
							int segAnt = ant;

							//System.out.println("2x = " + s[p].x + ", y = " + s[p].y + ", p = " + p);

							Ponto iniAnt = buscaPonto(s, 0, segAnt, true);
							Ponto fimAnt = buscaPonto(s, p, segAnt, false);
							Ponto fim1 = buscaPonto(s, p, s[p].seg, false);

							if (fim1 != null && iniAnt != null && fimAnt != null) {
								if (segmentosSeInterceptam(iniAnt, fimAnt, s[p], fim1)) {
									return true;
								}
							}

						}

					}

					ant = next;
				}
			} else if (!s[p].esq) {

				it = ll.iterator();
				ant = -1;

				while (it.hasNext()) {

					Iterator<Integer> temp = it;
					int next = temp.next();
					//System.out.println("next = " + next);
					if (next == s[p].seg) {

						// Se existe um segmento acima e outro abaixo do atual
						if ((ant != -1)) {

							int seg2 = next;

							//System.out.println("3x = " + s[p].x + ", y = " + s[p].y + ", p = " + p);

							Ponto ini2 = buscaPonto(s, 0, seg2, true);
							Ponto fim2 = buscaPonto(s, p, seg2, false);

							// Iterator<Integer> temp2 = ant;
							int segAnt = ant;
							Ponto iniAnt = buscaPonto(s, 0, segAnt, true);
							Ponto fimAnt = buscaPonto(s, p, segAnt, false);

							if (fimAnt != null && ini2 != null && fim2 != null && iniAnt != null && segAnt != seg2) {
								if (segmentosSeInterceptam(ini2, fim2, iniAnt, fimAnt)) {
									return true;
								}
							}
						}

					}

					ant = next;
				}
				Integer rem = s[p].seg;
				ll.remove(rem);

			}

		}
		return false;
	}

	Ponto buscaPonto(Ponto[] s, int ini, int seg, boolean esq) {
		for (int i = ini; ini < s.length; i++) {
			if (s[i].seg == seg && s[i].esq == esq) {
				return s[i];
			}
		}
		return null;
	}

	void ordenaExtremidades(Ponto[] s) {

		for (int i = 1; i < s.length; i++) {

			Ponto v = s[i];
			int j = i;

			while ((j > 0)) {
				if (s[j - 1].x > v.x) {
					s[j] = s[j - 1];
					j--;
				} else if (s[j - 1].x == v.x) {
					if (!s[j - 1].esq && v.esq) {
						s[j] = s[j - 1];
						j--;
					} else if (s[j - 1].esq == v.esq) {
						if (s[j - 1].y > v.y) {
							s[j] = s[j - 1];
							j--;
						} else {
							break;
						}
					} else {
						break;
					}
				} else {
					break;
				}
			}
			s[j] = v;

		}
	}

	public static void main(String[] args) {

		GuardDuty gd = new GuardDuty();
		Scanner in = new Scanner(System.in);

		int r = in.nextInt();
		int b = in.nextInt();

		if (r != b) {
			System.out.println("No");
			in.close();
			System.exit(0);
			//return;
		}

		Ponto[] navesBases = new Ponto[r + b];

		int x, y;
		// Naves na primeira metade
		for (int i = 0; i < r; i++) {

			x = in.nextInt();
			y = in.nextInt();

			navesBases[i] = new Ponto(x, y, true);
		}

		// Bases na segunda metade
		for (int j = r; j < navesBases.length; j++) {

			x = in.nextInt();
			y = in.nextInt();

			navesBases[j] = new Ponto(x, y, false);
		}

		for (int k = 0; k < r; k++) {
			for (int l = r; l < navesBases.length; l++) {
				navesBases[l].seg = l - r + 1;

				if (l + k - r < r) {
					navesBases[l + k - r].seg = l - r + 1;

					if (navesBases[l].x < navesBases[l + k - r].x) {
						navesBases[l].esq = true;
						navesBases[l + k - r].esq = false;
					} else {
						navesBases[l].esq = false;
						navesBases[l + k - r].esq = true;
					}

				} else {

					navesBases[l + k - 2 * r].seg = l - r + 1;
					if (navesBases[l].x < navesBases[l + k - 2 * r].x) {

						navesBases[l].esq = true;
						navesBases[l + k - 2 * r].esq = false;
					} else {
						navesBases[l].esq = false;
						navesBases[l + k - 2 * r].esq = true;
					}

				}

			}

			if(gd.nSegmentosInterceptam(navesBases)) {
				System.out.println("Yes");
				in.close();
				System.exit(1);
				//return;
			}
		}

		System.out.println("No");
		in.close();
		System.exit(0);
	}

}

class Ponto {

	public int x;
	public int y;
	public int seg;
	public boolean esq;
	public boolean nave;

	public Ponto(int x, int y, boolean nave) {
		super();
		this.x = x;
		this.y = y;
		this.nave = nave;
	}

}


import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.*;
import java.util.*;

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

	int[][] ships;
	int[][] bases;
	int n, m;

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

		n = fs.nextInt();
		m = fs.nextInt();
		ships = new int[2][n];
		bases = new int[2][n];
		for(int i = 0; i < n; i++) {
			ships[0][i] = fs.nextInt();
			ships[1][i] = fs.nextInt();
		}
		for(int i = 0; i < m; i++) {
			bases[0][i] = fs.nextInt();
			bases[1][i] = fs.nextInt();
		}

		if(n != m) {
			System.out.println("No");
			return;
		}

		rec(0, new boolean[m], new int[n]);

		if(found) out.println("Yes");
		else out.println("No");

		out.close();
	}

	boolean found = false;

	void rec(int at, boolean[] used, int[] with) {
		if(at == used.length) {
			if(good(with)) {
				found = true;
			}
			return;
		}

		for(int i = 0; i < used.length && !found; i++) {
			if(used[i]) continue;
			used[i] = true;
			with[at] = i;
			rec(at+1, used, with);
			used[i] = false;
		}

	}

	boolean good(int[] with) {
		Line[] lines = new Line[n];
		for(int i = 0; i < n; i++) {
			lines[i] = new Line(ships[0][i], ships[1][i], bases[0][with[i]], bases[1][with[i]]);
		}
		for(int i = 0; i < n; i++) {
			for(int j = i + 1; j < n; j++) {
				if(lines[i].intersectsLine(lines[j])) return false;
			}
		}
		return true;
	}

	class Line extends Line2D {

		@Override
		public Rectangle2D getBounds2D() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public Point2D getP1() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public Point2D getP2() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public double getX1() {
			// TODO Auto-generated method stub
			return x1;
		}

		@Override
		public double getX2() {
			// TODO Auto-generated method stub
			return x2;
		}

		@Override
		public double getY1() {
			// TODO Auto-generated method stub
			return y1;
		}

		@Override
		public double getY2() {
			// TODO Auto-generated method stub
			return y2;
		}

		double x1, y1, x2, y2;
		@Override
		public void setLine(double arg0, double arg1, double arg2, double arg3) {
			// TODO Auto-generated method stub
			x1 = arg0; y1 = arg1; x2 = arg2; y2 = arg3;
		}

		Line(int a, int b, int c, int d) { setLine(a, b, c, d); }

	}

	void sort (int[] a) {
		int n = a.length;
		for(int i = 0; i < 50; i++) {
			Random r = new Random();
			int x = r.nextInt(n), y = r.nextInt(n);
			int temp = a[x];
			a[x] = a[y];
			a[y] = temp;
		}
		Arrays.sort(a);
	}

	class DeoxysS {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public DeoxysS() {
			in = new BufferedInputStream(System.in, BS);
		}

		public DeoxysS(String s) throws FileNotFoundException {
			in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

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

	}

}


import java.util.Scanner;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Madi
 */
public class TRafficLights {
    public static void main(String [] args) {
        Scanner sc = new Scanner(System.in);
        String [] line = sc.nextLine().split(" ");
        int l = Integer.parseInt(line[0]);
        int d = Integer.parseInt(line[1]);
        int v = Integer.parseInt(line[2]);
        int g = Integer.parseInt(line[3]);
        int r = Integer.parseInt(line[4]);

        double doSvetofora = (double)d / (double)v;
        double ost = doSvetofora;
        while (ost >= 0) {
            ost -= (g + r);
        }

        ost += (g + r);
        double doroga = 0;
        if (ost >= 0 && ost < g) {
            doroga = (double) l / (double) v;
        } else {
            doroga = doSvetofora + (r + g - ost) + (double) (l - d) / (double) v;
        }

        System.out.println(doroga);
    }
}


public class a {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int L = in.nextInt();
        int d = in.nextInt();
        int v = in.nextInt();
        int g = in.nextInt();
        int r = in.nextInt();

        double t = (double)d / v;
        int time = (int)(t / (g + r)) * (g + r);
     //    final double eps = 1e-9;

        if (time + g < t) {
            t = time + (g + r);
        }
        System.out.format("%.10f\n", t + (double)(L - d) / v);
    }
}


import java.io.IOException;
import java.util.Scanner;

public class Main {
    public double l, d, v, g, r;

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

    public void read() {
        try {
            // Scanner sc = new Scanner(new File("input.txt"));

            Scanner sc = new Scanner(System.in);

            String[] ss = sc.nextLine().split(" ");

            l = Double.parseDouble(ss[0]);
            d = Double.parseDouble(ss[1]);
            v = Double.parseDouble(ss[2]);
            g = Double.parseDouble(ss[3]);
            r = Double.parseDouble(ss[4]);

        } catch ( Exception _ex ) {
            _ex.printStackTrace();
        }
    }

    public void solve() {
        double t = d / v;
        if ( t <= g ) {
            t += (l - d) / v;
        } else {
            t += r;
        }

        System.out.printf("%.8f", t);
    }

    public void write() {
        try {
            // BufferedWriter bw = new BufferedWriter(new
            // FileWriter("output.txt"));

            System.out.println();
        } catch ( Exception _ex ) {
            _ex.printStackTrace();
        }
    }

}