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

public class C {
	void run() {
		int n = in.nextInt();
		int place = in.nextInt();
		if (place == n + 1) {
			System.out.println(0);
			return;
		}
		int needBeHigher = n + 1 - place;
		long inf = Long.MAX_VALUE / 3;
		long ans = inf;
//		Map<Integer, List<Integer>> map = new TreeMap<>();
//		Participant[] participants = new Participant[n];
		int[] points = new int[n];
		int[] effort = new int[n];
		for (int i = 0; i < n; i++) {
//			participants[i] = new Participant(in.nextInt(), in.nextInt());
			points[i] = in.nextInt();
			effort[i] = in.nextInt();
//			if (!map.containsKey(points)) {
//				map.put(points, new ArrayList<Integer>());
//			}
//			map.get(points).add(efforts);
		}
		int[] allPoints = points.clone();
		Arrays.sort(allPoints);
		int needPoints = allPoints[n - place];
		for (int gotPoints = needPoints; gotPoints <= needPoints + 2; gotPoints++) {
			List<Integer> a = new ArrayList<>();
			List<Integer> b = new ArrayList<>();
			int c = 0;
			for (int i = 0; i < n; i++) {
				int p = points[i];
				int e = effort[i];
				if (p > gotPoints) {
					a.add(e);
				} else if (p == gotPoints || p == gotPoints - 1) {
					b.add(e);
				} else {
					a.add(e);
					c++;
				}
			}
			Collections.sort(a);
			Collections.sort(b);
			long cur = 0;
			int takeB = needBeHigher - c;
			if (takeB > b.size()) {
				continue;
			}
			if (takeB < 0) {
				takeB = 0;
			}
			int score = 0;
			int ai = 0;
			int bi = 0;
			while (takeB > 0) {
				takeB--;
				cur += b.get(bi);
				bi++;
				score++;
			}
			while (score < gotPoints) {
				if (bi < b.size() && (ai == a.size() || b.get(bi) < a.get(ai))) {
					cur += b.get(bi);
					bi++;
					score++;
				} else if (ai < a.size()) {
					cur += a.get(ai);
					ai++;
					score++;
				} else {
					break;
				}
			}
			if (score >= gotPoints) {
				ans = Math.min(ans, cur);
			}
		}
//		int mustDefeat = n + 1 - place;
//		int defeated = 0;
//		for (int p : map.keySet()) {
//			List<Integer> curList = map.get(p);
//			Collections.sort(curList);
//		}
		System.out.println(ans == inf ? -1 : ans);
	}

//	class Participant implements Comparable<Participant> {
//		int points;
//		int effort;
//
//		public Participant(int points, int effort) {
//			this.points = points;
//			this.effort = effort;
//		}
//
//		@Override
//		public int compareTo(Participant o) {
//			return 0;
//		}
//	}

	static boolean stdStreams = true;
	static String fileName = C.class.getSimpleName().replaceFirst("_.*", "").toLowerCase();
	static String inputFileName = fileName + ".in";
	static String outputFileName = fileName + ".out";
	static MyScanner in;
	static PrintWriter out;

	public static void main(String[] args) throws IOException {
		Locale.setDefault(Locale.US);
		BufferedReader br;
		if (stdStreams) {
			br = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
		} else {
			br = new BufferedReader(new FileReader(inputFileName));
			out = new PrintWriter(outputFileName);
		}
		in = new MyScanner(br);
		new C().run();
		br.close();
		out.close();
	}

	static class MyScanner {
		BufferedReader br;
		StringTokenizer st;

		MyScanner(BufferedReader br) {
			this.br = br;
		}

		void findToken() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
		}

		String next() {
			findToken();
			return st.nextToken();
		}

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

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

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


import java.util.*; //Scanner;
import java.io.PrintWriter; //PrintWriter

public class R229_Rocket_C1 //Name: The Tournament
{
	public static void main(String[] args) {
		Scanner      in = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		solve(in, out);
		out.close();
		in.close();
	}

	public static void solve(Scanner in, PrintWriter out)
	{
		int n = in.nextInt();
		int k = in.nextInt();

		int[] p = new int[n];
		int[] e = new int[n];
		for (int i = 0; i < n; i++)
		{
			p[i] = in.nextInt();
			e[i] = in.nextInt();
		}

		int minEffort = Integer.MAX_VALUE;
		for (int bitmask = 0; bitmask < 1<<n; bitmask++) //2^n
		{
			int win = 0, effort = 0;
			int[] p2 = new int[n];
			boolean[] won = new boolean[n];
			for (int i = 0; i < n; i++) p2[i] = p[i];
			for (int j = 0; j < n; j++)
				if ((bitmask & (1 << j)) != 0) //win
				{
					win++;
					effort += e[j];
					won[j] = true;
				}
				else //lose
				{
					p2[j]++;
				}

			Arrays.sort(p2);
			int place = n+1;
			int i = 0;
			while (i < n && p2[i] < win)
			{
				i++; place--;
			}

			if (i < n && p2[i] == win)
			{
				for (int j = 0; j < n; j++)
					if (p[j]==win && won[j]) place--;
			}

			if (place <= k)
				minEffort = Math.min(minEffort,  effort);

		}
		if (minEffort == Integer.MAX_VALUE)
			out.println(-1);
		else
			out.println(minEffort);
	}
}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.PriorityQueue;

public class CF {
	static int cmp;
	public static void main(String[] args) {
		FasterScanner sc = new FasterScanner();
		PrintWriter out = new PrintWriter(System.out);
		int N = sc.nextInt();
		int K = sc.nextInt()-1;
		PriorityQueue<Person> TIE = new PriorityQueue<Person>();
		PriorityQueue<Person> OTHER = new PriorityQueue<Person>();
		Person[] ppl = new Person[N];
		for(int a=0;a<N;a++){
			ppl[a]=new Person(sc.nextInt(),sc.nextInt());
		}
		cmp = 0;
		Arrays.sort(ppl);
		int safe = -1;
		int i = K;
		int goal = ppl[K].P;
		while(ppl[i].P==goal){
			safe++;
			if(i==0)break;
			i--;
		}
		if(ppl[K].P>N){
			out.println("-1");
			out.close();
			return;
		}
//		System.out.println(safe+" "+K);
		cmp = 1;
		PriorityQueue<Person> LAZY = new PriorityQueue<Person>();
		for(int a=0;a<N;a++){
			LAZY.add(ppl[a]);
			if(ppl[a].P==goal||ppl[a].P==goal-1)
				TIE.add(ppl[a]);
			else OTHER.add(ppl[a]);
		}
		long used = 0;
		long eff2 = 0;
		for(int a=0;a<=goal;a++){
			eff2+=LAZY.poll().E;
		}

		while(TIE.size()>safe){
			used+=TIE.poll().E;
			goal--;
//			System.out.println("H");
//			if(goal<=0)break;
		}
		OTHER.addAll(TIE);
		while(goal>0){
			K++;
			used+=OTHER.poll().E;
		}

		out.println(Math.min(used,eff2));

		out.close();
	}

	static class Person implements Comparable<Person>{
		int P,E;
		Person(int p, int e){
			P=p;
			E=e;
		}
		@Override
		public int compareTo(Person o) {
			if(cmp==0)return o.P-this.P;
			return this.E-o.E;
		}
	}

	static class FasterScanner{
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FasterScanner(){
			stream = System.in;
			//stream = new FileInputStream(new File("dec.in"));

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

		boolean isSpaceChar(int c){
			return c==' '||c=='\n'||c=='\r'||c=='\t'||c==-1;
		}
		boolean isEndline(int c){
			return c=='\n'||c=='\r'||c==-1;
		}
		int nextInt(){
			return Integer.parseInt(next());
		}
		long nextLong(){
			return Long.parseLong(next());
		}
		double nextDouble(){
			return Double.parseDouble(next());
		}
		String next(){
			int c = read();
			while(isSpaceChar(c))
				c=read();
			StringBuilder res = new StringBuilder();
			do{
				res.appendCodePoint(c);
				c=read();
			} while(!isSpaceChar(c));
			return res.toString();
		}
		String nextLine(){
			int c = read();
			while(isEndline(c))
				c=read();
			StringBuilder res = new StringBuilder();
			do{
				res.appendCodePoint(c);
				c = read();
			}while(!isEndline(c));
			return res.toString();
		}

	}

}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.PriorityQueue;

public class CF {
	static int cmp;
	public static void main(String[] args) {
		FasterScanner sc = new FasterScanner();
		PrintWriter out = new PrintWriter(System.out);
		int N = sc.nextInt();
		int K = sc.nextInt()-1;
		PriorityQueue<Person> TIE = new PriorityQueue<Person>();
		PriorityQueue<Person> OTHER = new PriorityQueue<Person>();
		Person[] ppl = new Person[N];
		for(int a=0;a<N;a++){
			ppl[a]=new Person(sc.nextInt(),sc.nextInt());
		}
		cmp = 0;
		Arrays.sort(ppl);
		int safe = -1;
		int i = K;
		int goal = ppl[K].P;
		while(ppl[i].P==goal){
			safe++;
			if(i==0)break;
			i--;
		}
		if(ppl[K].P>N){
			out.println("-1");
			out.close();
			return;
		}
//		System.out.println(safe+" "+K);
		cmp = 1;
		PriorityQueue<Person> LAZY = new PriorityQueue<Person>();
		for(int a=0;a<N;a++){
			LAZY.add(ppl[a]);
			if(ppl[a].P==goal||ppl[a].P==goal-1)
				TIE.add(ppl[a]);
			else OTHER.add(ppl[a]);
		}
		long used = 0;
		long eff2 = 0;
		for(int a=0;a<=goal;a++){
			if(LAZY.isEmpty())eff2 = Long.MAX_VALUE;
			else eff2+=LAZY.poll().E;
		}

		while(TIE.size()>safe){
			used+=TIE.poll().E;
			goal--;
//			System.out.println("H");
//			if(goal<=0)break;
		}
		OTHER.addAll(TIE);
		while(goal>0){
			K++;
			used+=OTHER.poll().E;
		}

		out.println(Math.min(used,eff2));

		out.close();
	}

	static class Person implements Comparable<Person>{
		int P,E;
		Person(int p, int e){
			P=p;
			E=e;
		}
		@Override
		public int compareTo(Person o) {
			if(cmp==0)return o.P-this.P;
			return this.E-o.E;
		}
	}

	static class FasterScanner{
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FasterScanner(){
			stream = System.in;
			//stream = new FileInputStream(new File("dec.in"));

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

		boolean isSpaceChar(int c){
			return c==' '||c=='\n'||c=='\r'||c=='\t'||c==-1;
		}
		boolean isEndline(int c){
			return c=='\n'||c=='\r'||c==-1;
		}
		int nextInt(){
			return Integer.parseInt(next());
		}
		long nextLong(){
			return Long.parseLong(next());
		}
		double nextDouble(){
			return Double.parseDouble(next());
		}
		String next(){
			int c = read();
			while(isSpaceChar(c))
				c=read();
			StringBuilder res = new StringBuilder();
			do{
				res.appendCodePoint(c);
				c=read();
			} while(!isSpaceChar(c));
			return res.toString();
		}
		String nextLine(){
			int c = read();
			while(isEndline(c))
				c=read();
			StringBuilder res = new StringBuilder();
			do{
				res.appendCodePoint(c);
				c = read();
			}while(!isEndline(c));
			return res.toString();
		}

	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class C {
    static int rec(int idx, int[] a, int[] b) {
        final int len = (1 << idx) - 1;
        final int mid = len / 2;
        if(a[0] >= a[1] || b[0] >= b[1])
            return 0;

//      System.err.println(a[0] + " " + a[1] + " " + b[0] + " " + b[1]);

        if(a[0] > b[0]) {
            final int[] c = a; a = b; b = c;
        }

        if(a[0] <= b[0] && b[1] <= a[1]) {
            return b[1] - b[0];
        }

        int res = 0;
        res = Math.max(Math.min(a[1], b[1]) - Math.max(a[0], b[0]), res);

        int[][][] rng = new int[2][2][2];
        rng[0][0][0] = a[0];
        rng[0][0][1] = Math.min(a[1], mid);

        rng[0][1][0] = Math.max(a[0] - 1, mid) - mid;
        rng[0][1][1] = a[1] - mid - 1;

        rng[1][0][0] = b[0];
        rng[1][0][1] = Math.min(b[1], mid);

        rng[1][1][0] = Math.max(b[0] - 1, mid) - mid;
        rng[1][1][1] = b[1] - mid - 1;

        for(int i = 0; i < 2; i++)
            for(int j = 0; j < 2; j++)
                res = Math.max(res, rec(idx - 1, rng[0][i], rng[1][j]));

        return res;
    }

    public static void main(String[] args) throws IOException {
        final int l1 = IOFast.nextInt();
        final int r1 = IOFast.nextInt();
        final int l2 = IOFast.nextInt();
        final int r2 = IOFast.nextInt();
        IOFast.out.println(rec(30, new int[] { l1 - 1, r1 }, new int[] { l2 - 1, r2 }));

        IOFast.out.flush();
    }

    static public class IOFast {
        private static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        private static PrintWriter out = new PrintWriter(System.out);

//      private static final int BUFFER_SIZE = 50 * 200000;
        private static final StringBuilder buf = new StringBuilder();
        private static boolean[] isDigit = new boolean[256];
        private static boolean[] isSpace = new boolean[256];

        static {
            for(int i = 0; i < 10; i++) {
                isDigit['0' + i] = true;
            }
            isDigit['-'] = true;
            isSpace[' '] = isSpace['\r'] = isSpace['\n'] = isSpace['\t'] = true;
        }

        static boolean endInput;

        private static int nextInt() throws IOException {
            boolean plus = false;
            int ret = 0;
            while(true) {
                final int c = in.read();

                if(c == -1) {
                    endInput = true;
                    return Integer.MIN_VALUE;
                }

                if(isDigit[c]) {
                    if(c != '-') {
                        plus = true;
                        ret = c - '0';
                    }
                    break;
                }
            }

            while(true) {
                final int c = in.read();
                if(c == -1 || !isDigit[c]) {
                    break;
                }
                ret = ret * 10 + c - '0';
            }

            return plus ? ret : -ret;
        }

        private static long nextLong() throws IOException {
            boolean plus = false;
            long ret = 0;
            while(true) {
                final int c = in.read();

                if(c == -1) {
                    endInput = true;
                    return Integer.MIN_VALUE;
                }

                if(isDigit[c]) {
                    if(c != '-') {
                        plus = true;
                        ret = c - '0';
                    }
                    break;
                }
            }

            while(true) {
                final int c = in.read();
                if(c == -1 || !isDigit[c]) {
                    break;
                }
                ret = ret * 10 + c - '0';
            }

            return plus ? ret : -ret;
        }

        private static String next() throws IOException {
            buf.setLength(0);

            while(true) {
                final int c = in.read();

                if(c == -1) {
                    endInput = true;
                    return "-1";
                }

                if(!isSpace[c]) {
                    buf.append((char)c);
                    break;
                }
            }

            while(true) {
                final int c = in.read();

                if(c == -1 || isSpace[c]) {
                    break;
                }
                buf.append((char)c);
            }

            return buf.toString();
        }

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

    }

}


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

public class C {
	static BufferedReader in;
	static StringTokenizer strtok;

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

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

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

	static double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}
	static int ans = 0;

	static void Calc(int level, int l1, int r1, int l2, int r2) {
		if (l1 > r1 || l2 > r2) return;

		if (l1 == 0 && r1 == (1 << level) - 1) {
			ans = Math.max(ans, r2 - l2 + 1);
			return;
		}

		if (l2 == 0 && r2 == (1 << level) - 1) {
			ans = Math.max(ans, r1 - r1 + 1);
			return;
		}

		ans = Math.max(ans, Math.min(r2, r1) - Math.max(l2, l1) + 1);
		int mid = (1 << (level - 1)) - 1;

		int L1 = l1, R1 = r1, L2 = l2, R2 = r2;

		for (int i = 0; i < 2; ++i) {
			int sl = 0, sr = mid - 1;
			if (i == 1) {
				sl = mid + 1;
				sr = (1 << level) - 1;
			}

			l1 = Math.max(L1, sl); r1 = Math.min(R1, sr);

			for (int j = 0; j < 2; ++j) {
				int sl1 = 0, sr1 = mid - 1;
				if (j == 1) {
					sl1 = mid + 1;
					sr1 = (1 << level) - 1;
				}

				l2 = Math.max(L2, sl1); r2 = Math.min(R2, sr1);
				Calc(level - 1, l1 - sl, r1 - sl, l2 - sl1, r2 - sl1);
			}
		}
	}

	public static void main(String args[]) throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(System.out);
		int l1 = nextInt() - 1, r1 = nextInt() - 1;
		int l2 = nextInt() - 1, r2 = nextInt() - 1;
		Calc(30 , l1, r1, l2, r2);
		out.println(ans);
		out.close();
	}
}


import java.io.InputStreamReader;
import java.io.IOException;
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) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskC solver = new TaskC();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskC {
    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int l1 = in.nextInt();
        int r1 = in.nextInt();
        int l2 = in.nextInt();
        int r2 = in.nextInt();
        int len = 1;
        for (int step = 0; step < 30; ++step) {
            len = len * 2 + 1;
        }
        long res = rec(l1, r1, l2, r2, len);
        out.println(res);
    }

    private long rec(int l1, int r1, int l2, int r2, int len) {
        if (len == 0) {
            return 0;
        }
        if (l1 > r1 || l2 > r2) return 0;
        int center = (len / 2) + 1;
        if (r1 < center && r2 < center) {
            return rec(l1, r1, l2, r2, len / 2);
        }
        if (l1 > center && l2 > center) {
            return rec(len - r1 + 1, len - l1 + 1, len - r2 + 1, len - l2 + 1, len / 2);
        }
        if (r1 < center && l2 > center) {
            return rec(l1, r1, len - r2 + 1, len - l2 + 1, len / 2);
        }
        if (r2 < center && l1 > center) {
            return rec(l2, r2, l1, r1, len);
        }
        if (l1 <= center && r1 >= center) {
            if (l2 <= center && r2 >= center) {
                long max = rec(l1, center-1, l2, r2, len);
                max = Math.max(max, rec(center + 1, r1, l2, r2, len));
                int le = Math.max(l1, l2);
                int ri = Math.min(r1, r2);
                if (le <= ri) {
                    max = Math.max(max, ri - le + 1);
                }
                l1 = len - l1 + 1;
                r1 = len - r1 + 1;
                le = Math.max(l1, l2);
                ri = Math.min(r1, r2);
                if (le <= ri) {
                    max = Math.max(max, ri - le + 1);
                }
                return max;
            } else {
                long max = rec(l1, center-1, l2, r2, len);
                max = Math.max(max, rec(center + 1, r1, l2, r2, len));
                return max;
            }
        }
        if (l2 <= center && r2 >= center) {
            return rec(l2, r2, l1, r1, len);
        }
        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());
    }

}


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

public class C {
	BufferedReader in;
	StringTokenizer str;
	PrintWriter out;
	String SK;

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

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

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

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

	int[] len;
	int[] pos;

	int solve(int l1, int r1, int l2, int r2, int type) {
		if (l1 > r1 || l2 > r2)
			return 0;
		if (l1 > l2) {
			return solve(l2, r2, l1, r1, type);
		}
		if (r2 <= r1) {
			return r2 - l2 + 1;
		}
		if (l1 == l2) {
			return Math.min(r2, r1) - l1 + 1;
		}
		if (r1 >= pos[type] && l2 <= pos[type]) {
			return Math.max(r1 - l2 + 1,
					solve(l1, pos[type] - 1, 0, r2 - pos[type] - 1, type - 1));
		}
		if (r1 >= pos[type]) {
			return solve(len[type] - r2 - 1, len[type] - l2 - 1, len[type] - r1
					- 1, len[type] - l1 - 1, type);
		}
		if (r2 < pos[type]) {
			return solve(l1, r1, l2, r2, type - 1);
		}
		return Math.max(
				solve(l1, r1, l2, pos[type], type - 1),
				solve(l1, r1, Math.max(0, l2 - pos[type] - 1), r2 - pos[type]
						- 1, type - 1));
	}

	void solve() throws IOException {
		int m = 30;
		len = new int[m];
		pos = new int[m];
		len[0] = 1;
		pos[0] = 0;
		for (int i = 1; i < m; i++) {
			pos[i] = len[i - 1];
			len[i] = 2 * len[i - 1] + 1;
		}
		out.println(solve(nextInt() - 1, nextInt() - 1, nextInt() - 1,
				nextInt() - 1, m - 1));
	}

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

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

}


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

public class Solution {

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

	int p;

	long[][] pow(long[][] x, long pow) {
		long[][] r = new long[x.length][x.length];
		for (int i = 0; i < x.length; ++i) {
			r[i][i] = 1;
		}
		while (pow > 0) {
			if (pow % 2 == 1) {
				r = mul(r, x);
			}
			pow /= 2;
			x = mul(x, x);
		}
		return r;
	}

	long[][] mul(long[][] a, long[][] b) {
		long[][] c = new long[a.length][a.length];
		for (int i = 0; i < a.length; ++i) {
			for (int j = 0; j < a.length; ++j) {
				for (int k = 0; k < a.length; ++k) {
					c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % p;
				}
			}
		}
		return c;
	}

	void solve() throws IOException {
		int n = nextInt();
		long x = nextLong();
		long y = nextLong();
		p = nextInt();
		long[] a = new long[n];
		long sum = 0;
		for (int i = 0; i < n; ++i) {
			a[i] = nextInt() % p;
			sum = (sum + a[i]) % p;
		}
		if (n == 1) {
			out.println(sum);
			return;
		}
		long[][] m1 = new long[][] {{3, p - 1}, {0, 1}};
		m1 = pow(m1, x);
		long sum1 = (m1[0][0] * sum + m1[0][1] * (a[0] + a[n - 1])) % p;
		long[][] f = new long[][] {{0, 1}, {1, 1}};
		f = pow(f, x);
		long ka = f[0][1];
		long kb = f[1][1];
		long[][] m2 = new long[][] {{3, p - 1}, {0, 1}};
		m2 = pow(m2, y);
		long sum2 = (m2[0][0] * sum1 + m2[0][1] * ((a[0] + ka * a[n - 2] + kb * a[n - 1]) % p)) % p;
		out.println(sum2);
	}

	Solution() throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);

		eat("");

		solve();

		in.close();
		out.close();
	}

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

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


import java.io.*;

//Codeforces Beta Round #56 (Div. 1), E
public class MushroomGnomes {

	public static void main(String[] args) throws IOException {
		File file = new File("input.txt");
		if(file.exists())
			System.setIn(new FileInputStream(file));
		BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
		String[] ss = r.readLine().split(" ");
		assert ss.length == 4;
		int n = Integer.parseInt(ss[0]);
		long x = Long.parseLong(ss[1]), y = Long.parseLong(ss[2]);
		int p = Integer.parseInt(ss[3]), lo = 0, m = 0, hi = 0;
		long sum = 0;
		String s = r.readLine();
		for(int i = 0, j = 0; i < n; i++) {
			int l = s.indexOf(' ', j);
			assert l != -1 || i == n - 1;
			int v = Integer.parseInt(l != -1 ? s.substring(j, l) : s.substring(j));
			if(j == 0)
				lo = v;
			if(l == -1)
				hi = v;
			if(i == n - 2)
				m = v;
			sum += v;
			j = l + 1;
		}

		int pow3x = pow(3, x, 2 * p), pow3y = pow(3, y, 2 * p);
		long result = sum % p;
		result *= pow3x;
		result += p;
		result -= (pow3x - 1l + 2 * p) % (2 * p) / 2 * (lo + hi) % p;
		result %= p;
		result *= pow3y;
		result += p;
		result -= (pow3y - 1l + 2 * p) % (2 * p) / 2 * (lo + fibonacci(m, hi, x + 1, p)) % p;
		result %= p;

		System.out.println(result);
	}

	private static int pow(long a, long n, int p) {
		long r = 1;
		while(n != 0) {
			if((n & 1) != 0)
				r = r * a  % p;
			a = a * a % p;
			n >>= 1;
		}
		return (int)r;
	}
	private static long[][] multiple(long[][] a, long[][] b, int p) {
		long r[][] = new long[a.length][b[0].length];
		for(int i = 0; i < r.length; i++) {
			for(int j = 0; j < r[i].length; j++) {
				for(int l = 0; l < a[i].length; l++)
					r[i][j] += a[i][l] * b[l][j];
				r[i][j] %= p;
			}
		}
		return r;
	}
	private static int fibonacci(int f0, int f1, long n, int p) {
		if(--n < 0)
			return f0;
		long[][] a = new long[][]{{0, 1}, {1, 1}}, r = new long[][]{{1, 0}, {0, 1}};
		while(n != 0) {
			if((n & 1) != 0)
				r = multiple(r, a, p);
			a = multiple(a, a, p);
			n >>= 1;
		}
		return (int)((f0 * r[1][0] + f1 * r[1][1]) % p);
	}

}


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

public class E implements Runnable {

	void solve() {
		int n = nextInt();
		long x = nextLong();
		long y = nextLong();
		int p = nextInt();
		int[] a = new int[n];
		if (n == 1) {
			out.println(nextInt() % p);
			return;
		}
		int min = Integer.MAX_VALUE;
		int sumAll = 0;
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
			min = Math.min(min, a[i]);
			sumAll = (sumAll + a[i]) % p;
		}
		int first = a[0];
		int last = n == 1 ? 0 : a[n - 1];
		int bestSum = Integer.MIN_VALUE;
		int bestMax = Integer.MIN_VALUE;
		for (int i = 0; i + 1 < n; i++) {
			if (a[i] + a[i + 1] > bestSum
					|| (a[i] + a[i + 1] == bestSum && Math.max(a[i], a[i + 1]) > bestMax)) {
				bestSum = a[i] + a[i + 1];
				bestMax = Math.max(a[i], a[i + 1]);
			}
		}
		int sum1;
		int max;
		if (x == 0) {
			max = Integer.MIN_VALUE;
			for (int i = 0; i < n; i++) {
				max = Math.max(max, a[i]);
			}
			sum1 = sumAll;
		} else {
			int got = getIt(sumAll, first, last, p, x);
			sum1 = (got) % p;
			max = getFib(bestSum - bestMax, bestMax, x, p);
		}
		int sum2;
		if (y == 0) {
			sum2 = sum1;
		} else {
			sum2 = (getIt(sum1, min, max, p, y)) % p;
		}
		out.println((sum2) % p);
	}

	int getIt(int sum, int a, int b, int p, long t) {
		int ret = (int) ((((long) sum - a - b) % p + p) % p * modPow(3, t, p) % p);
		ret = (int) ((ret + ((long) a + b) % p * (1 + sumPow(3, t, p))) % p);
		return ret;
	}

	int sumPow(int a, long b, int mod) {
		int ret = 0;
		int c = 1;
		while (b > 0) {
			if ((b & 1) == 1) {
				ret = (int) (((long) ret * a + c) % mod);
			}
			c = (int) (((long) c * a + c) % mod);
			a = (int) ((long) a * a % mod);
			b >>= 1;
		}
		return ret;
	}

	int getFib(int a, int b, long n, int p) {
		Matrix m = new Matrix(2);
		m.a[0][0] = m.a[0][1] = m.a[1][0] = 1;
		m = modPow(m, n, p);
		return (int) (((long) m.a[0][0] * b + (long) m.a[0][1] * a) % p);
	}

	static class Matrix {
		int[][] a;
		int n;

		Matrix(int n) {
			this.n = n;
			a = new int[n][n];
		}

		Matrix multiply(Matrix b, int p) {
			Matrix ret = new Matrix(n);
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < n; j++) {
					int got = 0;
					for (int k = 0; k < n; k++) {
						got = (int) ((got + (long) a[i][k] * b.a[k][j] % p) % p);
					}
					ret.a[i][j] = got;
				}
			}
			return ret;
		}

	}

	Matrix modPow(Matrix a, long b, int p) {
		int n = a.n;
		Matrix ret = new Matrix(n);
		for (int i = 0; i < n; i++) {
			ret.a[i][i] = 1;
		}
		while (b > 0) {
			if ((b & 1) == 1) {
				ret = ret.multiply(a, p);
			}
			a = a.multiply(a, p);
			b >>= 1;
		}
		return ret;
	}

	int modPow(int a, long b, int p) {
		int ret = 1;
		while (b > 0) {
			if ((b & 1) == 1) {
				ret = (int) ((long) ret * a % p);
			}
			a = (int) ((long) a * a % p);
			b >>= 1;
		}
		return ret;
	}

	FastScanner sc;
	PrintWriter out;

	public void run() {
		Locale.setDefault(Locale.US);
		try {
			sc = new FastScanner(System.in);
			out = new PrintWriter(System.out);
			solve();
			sc.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	int nextInt() {
		return sc.nextInt();
	}

	String nextToken() {
		return sc.nextToken();
	}

	long nextLong() {
		return sc.nextLong();
	}

	double nextDouble() {
		return sc.nextDouble();
	}

	BigInteger nextBigInteger() {
		return sc.nextBigInteger();
	}

	class FastScanner extends BufferedReader {
		StringTokenizer st;
		boolean eof;
		String buf;
		String curLine;
		boolean createST;

		public FastScanner(String fileName) throws FileNotFoundException {
			this(fileName, true);
		}

		public FastScanner(String fileName, boolean createST)
				throws FileNotFoundException {
			super(new FileReader(fileName));
			this.createST = createST;
			nextToken();
		}

		public FastScanner(InputStream stream) {
			this(stream, true);
		}

		public FastScanner(InputStream stream, boolean createST) {
			super(new InputStreamReader(stream));
			this.createST = createST;
			nextToken();
		}

		String nextLine() {
			String ret = curLine;
			if (createST) {
				st = null;
			}
			nextToken();
			return ret;
		}

		String nextToken() {
			if (!createST) {
				try {
					curLine = readLine();
				} catch (Exception e) {
					eof = true;
				}
				return null;
			}
			while (st == null || !st.hasMoreTokens()) {
				try {
					curLine = readLine();
					st = new StringTokenizer(curLine);
				} catch (Exception e) {
					eof = true;
					break;
				}
			}
			String ret = buf;
			buf = eof ? "-1" : st.nextToken();
			return ret;
		}

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

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

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

		BigInteger nextBigInteger() {
			return new BigInteger(nextToken());
		}

		public void close() {
			try {
				buf = null;
				st = null;
				curLine = null;
				super.close();
			} catch (Exception e) {

			}
		}

		boolean isEOF() {
			return eof;
		}
	}

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


import static java.util.Arrays.deepToString;

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

public class Gnomes {

//  static final File F_IN              = new File("inout/cf/beta56/gnomes.in");
//  static final File F_OUT             = new File("inout/cf/beta56/gnomes.out");
    static final InputStream F_IN       = System.in;
    static final PrintStream F_OUT      = System.out;

    int n;
    long x, y, p;
    long[] a;
    long res;

    void readInput() throws Exception {
        Scanner sc = new Scanner(F_IN);
        n = sc.nextInt();
        x = sc.nextLong();
        y = sc.nextLong();
        p = sc.nextInt();
        a = new long[n];
        for (int i=0; i<n; i++) a[i] = sc.nextInt();
        sc.close();
    }

    void writeOutput() throws Exception {
        PrintWriter out = new PrintWriter(F_OUT);
        out.println(res);
        out.close();
    }

    long[][] mul(long[][] A, long[][] B) {
        long[][] C = new long[2][2];
        for (int i=0; i<2; i++)
            for (int j=0; j<2; j++)
                for (int k=0; k<2; k++) {
                    C[i][j] += A[i][k]*B[k][j];
                    C[i][j] %= p;
                }
        return C;
    }

    long[][] pow(long[][] A, long n) {
        if (n==0) return new long[][]{{1,0},{0,1}};
        if (n==1) return A;
        long[][] A2 = pow(A, n>>1);
        long[][] B = mul(A2, A2);
        if (n%2==1) return mul(B, A); else return B;
    }

    long afterX(long s0, long c, long x) {
        long[][] A = {{3, (p-c)%p}, {0, 1}};
        long[][] AX = pow(A, x);
        long res = AX[0][0]%p*s0%p + AX[0][1];
        return res % p;
    }

    long fibo(long n) {
        if (n==0) return 0;
        if (n<3) return 1;
        long[][] A = {{1,1},{1,0}};
        long[][] AN = pow(A, n-1);
        return AN[0][0]%p;
    }

    void solveProblem() {
        if (n==1) { res = a[0]; return ; }
        long s0 = 0;
        for (int i=0; i<n; i++) s0 += a[i];
        long afx = afterX(s0%p, (a[0]+a[n-1])%p, x);
        long maxAX = fibo(x)*a[n-2]+fibo(x+1)*a[n-1];
        maxAX %= p;
        long afy = afterX(afx%p, (a[0]+maxAX)%p, y);
        res = afy;
    }

    public Gnomes() throws Exception {
        readInput();
        solveProblem();
        writeOutput();
    }

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

    void debug(Object... os) {
        System.out.println(deepToString(os));
    }

}


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

public class C {

    private boolean greenCanMove(char[][] a) {
        for (int i = 0; i < a.length; ++i) {
            for (int j = 0; j < a[i].length; ++j) {
                if (a[i][j] == 'G') {
                    if (j > 0 && a[i][j - 1] == '-') {
                        return true;
                    }
                    if (j < a[i].length - 1 && a[i][j + 1] == '-') {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private boolean redCanMove(char[][] a) {
        for (int i = 0; i < a.length; ++i) {
            for (int j = 0; j < a[i].length; ++j) {
                if (a[i][j] == 'R') {
                    if (j > 0 && a[i][j - 1] == '-') {
                        return true;
                    }
                    if (j < a[i].length - 1 && a[i][j + 1] == '-') {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private int who(char[][] a, int n, int m, int k) {
        if (!greenCanMove(a)) {
            return 2;
        }

        if (!redCanMove(a)) {
            return 1;
        }

        ArrayList<Integer> stone = new ArrayList<Integer>();

        for (int i = 0; i < n; ++i) {
            int L = 0, R = m - 1;

            while (L < m && a[i][L] == '-') {
                ++L;
            }

            while (R >= 0 && a[i][R] == '-') {
                --R;
            }

            if (R < 0) {
                continue;
            }

            if (a[i][L] == a[i][R]) {
                return 0;
            }

            stone.add(R - L - 1);
        }

        boolean win = false;
        for (int bit = 0; bit <= 20; ++bit) {
            int sum = 0;
            for (int i = 0; i < stone.size(); ++i) {
                sum = sum + ((stone.get(i) >> bit) & 1);
            }
            if (sum % (k + 1) != 0) {
                win = true;
            }
        }

        return win ? 1 : 2;
    }

    public void run() {
        Scanner scanner = new Scanner(System.in);

        String[] args = scanner.nextLine().split(" ");

        int n = Integer.parseInt(args[0]);
        int m = Integer.parseInt(args[1]);
        int k = Integer.parseInt(args[2]);

        char[][] a = new char[n][];
        for (int i = 0; i < n; ++i) {
            a[i] = scanner.nextLine().toCharArray();
        }

        int ret = who(a, n, m, k);
        if (ret == 0) {
            System.out.println("Draw");
        } else if (ret == 1) {
            System.out.println("First");
        } else {
            System.out.println("Second");
        }

        scanner.close();
    }

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


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

public class A {

	public static void main(String[] args) throws IOException{
		Scanner sc = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		int R = sc.nextInt(), C = sc.nextInt(), k = sc.nextInt();
		ArrayList<String> piles = new ArrayList<>();
		boolean GNotLosing = false, RNotLosing = false;
		for(int i = 0; i < R; i++)
		{
			char[] row = sc.next().toCharArray();
			int s = -1, e = -1;
			char f = '#', l = '#';
			for(int j = 0; j < C; j++)
			{
				if(row[j] != '-' && s == -1)
				{
					s = j;
					f = row[j];
				}
				else if(row[j] != '-' && s != -1)
				{
					e = j;
					l = row[j];
				}
			}
			if(f == '#') continue;
			if(l == '#')
			{
				if(f == 'G' && row.length > 1) GNotLosing = true;
				else if(f == 'R' && row.length > 1)RNotLosing = true;
			}
			else if(f != l)
				piles.add(indent(Integer.toBinaryString(e - s - 1)));
			else
			{
				if(f == 'G' && row.length > 2) GNotLosing = true;
				else if(f == 'R' && row.length > 2)RNotLosing = true;
			}
		}
		if(RNotLosing && GNotLosing)
		{
			out.println("Draw");
			out.flush();
			return;
		}
		if(GNotLosing)
		{
			out.println("First");
			out.flush();
			return;
		}
		if(RNotLosing)
		{
			out.println("Second");
			out.flush();
			return;
		}
//		for(String pile : piles)
//			System.out.println(pile);

		for(int i = 0; i < 7; i++)
		{
			int c = 0;
			for(String pile : piles)
				c += pile.charAt(i) - '0';
			if(c % (k + 1) != 0)
			{
				out.println("First");
				out.flush();
				return;
			}
		}
		out.println("Second");
		out.flush();
	}

	static String indent(String s)
	{
		while(s.length() < 7) s = "0" + s;
		return s;
	}

	static class Scanner
	{
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream system) {br = new BufferedReader(new InputStreamReader(system));}
		public String next() throws IOException
		{
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}
		public String nextLine()throws IOException{return br.readLine();}
		public int nextInt() throws IOException {return Integer.parseInt(next());}
		public double nextDouble() throws IOException {return Double.parseDouble(next());}
		public char nextChar()throws IOException{return next().charAt(0);}
		public Long nextLong()throws IOException{return Long.parseLong(next());}
		public boolean ready() throws IOException{return br.ready();}
		public void waitForInput(){for(long i = 0; i < 3e9; i++);}
	}
}


import java.io.IOException;
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 {
	public void solve(int testNumber, InputReader in, OutputWriter out) {
		int rowCount = in.readInt();
		int columnCount = in.readInt();
		if (columnCount == 1) {
			out.printLine("Second");
			return;
		}
		int maxPerMove = in.readInt();
		char[][] field = IOUtils.readTable(in, rowCount, columnCount);
		if (columnCount == 2) {
			boolean firstCanMove = false;
			boolean secondCanMove = false;
			for (int i = 0; i < rowCount; i++) {
				if (field[i][0] == 'G' && field[i][1] == '-' || field[i][1] == 'G' && field[i][0] == '-')
					firstCanMove = true;
				if (field[i][0] == 'R' && field[i][1] == '-' || field[i][1] == 'R' && field[i][0] == '-')
					secondCanMove = true;
			}
			if (!firstCanMove)
				out.printLine("Second");
			else if (!secondCanMove)
				out.printLine("First");
			else
				out.printLine("Draw");
			return;
		}
		int[] distance = new int[rowCount];
		boolean firstCanSkip = false;
		boolean secondCanSkip = false;
		for (int i = 0; i < rowCount; i++) {
			int rPosition = -1;
			int gPosition = -1;
			for (int j = 0; j < columnCount; j++) {
				if (field[i][j] == 'G')
					gPosition = j;
				else if (field[i][j] == 'R')
					rPosition = j;
			}
			if (rPosition == -1) {
				if (gPosition != -1)
					firstCanSkip = true;
			} else if (gPosition == -1)
				secondCanSkip = true;
			else
				distance[i] = Math.abs(rPosition - gPosition) - 1;
		}
		if (firstCanSkip) {
			if (secondCanSkip) {
				out.printLine("Draw");
				return;
			}
			out.printLine("First");
			return;
		} else if (secondCanSkip) {
			out.printLine("Second");
			return;
		}
		for (int i = 0; i < 7; i++) {
			int current = 0;
			for (int j : distance)
				current += j >> i & 1;
			if (current % (maxPerMove + 1) != 0) {
				out.printLine("First");
				return;
			}
		}
		out.printLine("Second");
	}
}

class InputReader {

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

	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 static boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	public char readCharacter() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		return (char) c;
	}

	}

class OutputWriter {
	private final PrintWriter writer;

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

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

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

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

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

	}

class IOUtils {

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

	public static char[][] readTable(InputReader in, int rowCount, int columnCount) {
		char[][] table = new char[rowCount][];
		for (int i = 0; i < rowCount; i++)
			table[i] = readCharArray(in, columnCount);
		return table;
	}

	}


/**
 * Created by IntelliJ IDEA.
 * User: mac
 * Date: 12-1-12
 * Time: 下午10:52
 * To change this template use File | Settings | File Templates.
 */

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

public class d {

    BufferedReader reader;
    StringTokenizer tokenizer;
    PrintWriter writer;

    void run() {
        try {
            reader = new BufferedReader(new InputStreamReader(System.in));
            tokenizer = null;
            writer = new PrintWriter(System.out);
            solve();
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

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

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

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

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

    void solve() throws IOException {
        int n = nextInt(), m = nextInt(), k = nextInt();
        String[] lines = new String[n];
        int nR = 0, nG = 0;
        for (int i = 0; i < n; i++) {
            lines[i] = nextToken();
            for (char c : lines[i].toCharArray()) {
                if (c == 'R')
                    ++nR;
                if (c == 'G')
                    ++nG;
            }
        }
        if (nG == 0) {
            System.out.println("Second");
            return;
        }
        boolean cantDieR = false, cantDieG = false;

        if (m == 1) {
            System.out.println("Second");
            return;
        }

        int[] xor = new int[10];

        for (String line : lines) {
            boolean hasR = line.indexOf('R') >= 0, hasG = line.indexOf('G') >= 0;
            if (!hasR && !hasG)
                continue;
            if (hasR && hasG) {
                if (line.indexOf("RG") >= 0 || line.indexOf("GR") >= 0)
                    continue;

                int a = line.indexOf('R'), b = line.indexOf('G');
                int num = Math.abs(a - b) - 1;
                for (int i = 0; i < 10; i++) {
                    xor[i] += num % (k + 1);
                    num /= (k + 1);
                }
                continue;
            }
            if (hasR && !line.equals("RR"))
                cantDieR = true;
            if (hasG && !line.equals("GG"))
                cantDieG = true;
        }

        if (cantDieR && cantDieG) {
            System.out.println("Draw");
            return;
        }

        if (cantDieG) {
            System.out.println("First");
            return;
        }

        if (cantDieR) {
            System.out.println("Second");
            return;
        }

        for (int i : xor) {
            if (i % (k + 1) != 0) {
                System.out.println("First");
                return;
            }
        }
        System.out.println("Second");
    }

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


import java.util.Scanner;

public class F {
  static Scanner sc = new Scanner(System.in);
  static final double logE = Math.log(Math.E);

  public static void main(String[] args) {
    int V = sc.nextInt();
    double[] factLog = new double[4001];
    for (int i = 1; i < factLog.length; i++) {
      factLog[i] = Math.log(i) + factLog[i - 1];
    }
    for (int i = 0; i < V; i++) {
      int[] K = new int[10];
      int min = 0;
      for (int j = 0; j < K.length; j++) {
        K[j] = sc.nextInt();
        min = Math.min(K[j], min);
      }
      int max = 0;
      long sum = 0;
      long sum2 = 0;
      for (int j = 0; j < K.length; j++) {
        K[j] -= min;
        max = Math.max(max, K[j]);
        sum += K[j];
        sum2 += K[j] * K[j];
      }
      double ave = 1.0 * sum / K.length;
      double ave2 = 1.0 * sum2 / K.length;
      double var = ave2 - ave * ave;
      System.err.println("var:" + var);
      double uniform = -Math.log(2 * ((max + 1) / 2.0) + 1) * K.length;
      double poisson = -Double.MAX_VALUE;
      for (int j = Math.max(1, (int) var - 10); j <= (int) var + 150; j++) {
        double likelyhood = 0;
        for (int k = 0; k < K.length; k++) {
          likelyhood += K[k] * Math.log(j) - j * logE - factLog[K[k]];
        }
        if (likelyhood > poisson) {
          poisson = likelyhood;
        }
      }
      System.err.println(uniform + " " + poisson);
      System.out.println(uniform < poisson ? "poisson" : "uniform");
    }
  }

}


import java.util.Scanner;

public class F {
  static Scanner sc = new Scanner(System.in);
  static final double logE = Math.log(Math.E);

  public static void main(String[] args) {
    int V = sc.nextInt();
    double[] factLog = new double[4001];
    for (int i = 1; i < factLog.length; i++) {
      factLog[i] = Math.log(i) + factLog[i - 1];
    }
    for (int i = 0; i < V; i++) {
      int[] K = new int[250];
      int min = 0;
      for (int j = 0; j < K.length; j++) {
        K[j] = sc.nextInt();
        min = Math.min(K[j], min);
      }
      int max = 0;
      long sum = 0;
      long sum2 = 0;
      for (int j = 0; j < K.length; j++) {
        K[j] -= min;
        max = Math.max(max, K[j]);
        sum += K[j];
        sum2 += K[j] * K[j];
      }
      double ave = 1.0 * sum / K.length;
      double ave2 = 1.0 * sum2 / K.length;
      double var = ave2 - ave * ave;
      System.err.println("var:" + var);
      double uniform = -Math.log(2 * (max / 2.0) + 1) * K.length;
      double poisson = -Double.MAX_VALUE;
      for (int j = Math.max(1, (int) var - 100); j <= (int) var + 300; j++) {
        double likelyhood = 0;
        for (int k = 0; k < K.length; k++) {
          likelyhood += K[k] * Math.log(j) - j * logE - factLog[K[k]];
        }
        if (likelyhood > poisson) {
          poisson = likelyhood;
        }
      }
      System.err.println(uniform + " " + poisson);
      System.out.println(uniform < poisson ? "poisson" : "uniform");
    }
  }

}


import java.util.Scanner;

public class F {
  static Scanner sc = new Scanner(System.in);
  static final double logE = Math.log(Math.E);

  public static void main(String[] args) {
    int V = sc.nextInt();
    double[] factLog = new double[3001];
    for (int i = 1; i < factLog.length; i++) {
      factLog[i] = Math.log(i) + factLog[i - 1];
    }
    for (int i = 0; i < V; i++) {
      int[] K = new int[10];
      int min = 0;
      for (int j = 0; j < K.length; j++) {
        K[j] = sc.nextInt();
        Math.min(K[j], min);
      }
      int max = 0;
      long sum = 0;
      long sum2 = 0;
      for (int j = 0; j < K.length; j++) {
        K[j] -= min;
        max = Math.max(max, K[j]);
        sum += K[j];
        sum2 += K[j] * K[j];
      }
      double ave = 1.0 * sum / K.length;
      double ave2 = 1.0 * sum2 / K.length;
      double var = ave2 - ave * ave;
      double uniform = -Math.log(2 * ((max + 1) / 2.0) + 1) * K.length;
      double poisson = -Double.MAX_VALUE;
      for (int j = Math.max(1, (int) var - 10); j <= (int) var + 50; j++) {
        double likelyhood = 0;
        for (int k = 0; k < K.length; k++) {
          likelyhood += K[k] * Math.log(j) - j * logE;
        }
        if (likelyhood > poisson) {
          poisson = likelyhood;
        }
      }
      System.err.println(uniform + " " + poisson);
      System.out.println(uniform < poisson ? "poisson" : "uniform");
    }
  }

}


import java.util.Scanner;

public class F {
  static Scanner sc = new Scanner(System.in);
  static final double logE = Math.log(Math.E);

  public static void main(String[] args) {
    int V = sc.nextInt();
    double[] factLog = new double[1500001];
    for (int i = 1; i < factLog.length; i++) {
      factLog[i] = Math.log(i) + factLog[i - 1];
    }
    for (int i = 0; i < V; i++) {
      int[] K = new int[250];
      int min = 0;
      int max = 0;
      long sum = 0;
      long sum2 = 0;
      for (int j = 0; j < K.length; j++) {
        K[j] = sc.nextInt();
        min = Math.min(min, K[j]);
        max = Math.max(max, K[j]);
        sum += K[j];
        sum2 += K[j] * K[j];
      }
      double ave = 1.0 * sum / K.length;
      double ave2 = 1.0 * sum2 / K.length;
      double var = ave2 - ave * ave;
      System.err.println("var:" + var);
      double uniform = -Math.log(2 * Math.max(1, Math.max(-min, max)) + 1) * K.length;
      double poisson = -Double.MAX_VALUE;
      for (int j = Math.max(1, Math.max(-min, (int) var - 100)); j <= Math.min(1000, (int) var + 300); j++) {
        double likelyhood = 0;
        for (int k = 0; k < K.length; k++) {
          likelyhood += (K[k] + j) * Math.log(j) - j * logE - factLog[K[k] + j];
        }
        if (likelyhood > poisson) {
          poisson = likelyhood;
        }
      }
      System.err.println(uniform + " " + poisson);
      System.out.println(uniform < poisson ? "poisson" : "uniform");
    }
  }

}


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

public class Main {

    BufferedReader in;
    StringTokenizer str = null;
    PrintWriter out;

    private String next() throws Exception{
	if (str == null || !str.hasMoreElements())
	    str = new StringTokenizer(in.readLine());
	return str.nextToken();
    }

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

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

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

    int n, V, e, sumA, sumB, size, yk=0;
    int []a,b, comp, from, to, amount;
    int [][]adj;
    boolean []used,cused;

    public void run() throws Exception{
	in =  new BufferedReader(new InputStreamReader(System.in));
	out = new PrintWriter(System.out);
	n = nextInt(); V = nextInt(); e = nextInt();
	a = new int[n];
	b = new int[n];
	for(int i=0;i<n;i++){
	    a[i] = nextInt();
	}
	for(int i=0;i<n;i++){
	    b[i] = nextInt();
	}

	adj = new int[n][n];
	for(int i=0;i<e;i++){
	    int x = nextInt()-1;
	    int y = nextInt()-1;
	    adj[x][y] = adj[y][x] = 1;
	}

	from = new int[2*n*n+1];
	to = new int[2*n*n + 1];
	amount = new int[2*n*n+1];

	used = new boolean[n];
	boolean ok  = true;

	for(int i=0;i<n;i++){
	    if (!used[i]){
		sumA = 0;
		sumB = 0;
		size = 0;
		comp = new int[n];
		dfs(i);

		if (sumA != sumB){
		    ok = false;
		    break;
		}

		for(int j=0;j<size;j++){
		    cused = new boolean[n];
		    int x = comp[j];
		    if (a[x] < b[x]) pull(x, b[x] - a[x]);
		    if (a[x] > b[x]) push(x, a[x] - b[x]);
		}
	    }
	}

	if (!ok) {
	    out.println(-1);
	}else{
	    out.println(yk);
	    for(int i=0;i<yk;i++){
		out.println(from[i] + " " + to[i] + " " + amount[i]);
	    }
	}
	out.close();
    }

    private void push(int x, int d){
	cused[x] = true;
	for(int i=0;i<n;i++){
	    if (used[i] && !cused[i] && d > 0 && adj[x][i] == 2){
		if (V - a[i] < d){
		    int t = V - a[i];
		    a[x]-=t;
		    add(x+1, i+1, t);
		    push(i, t);
		    d-=t;
		}else{
		    a[x]-=d;
		    a[i]+=d;
		    add(x+1, i+1, d);
		    d = 0;
		}
	    }
	}
    }

    private void pull(int x, int d){
	cused[x] = true;
	for(int i=0;i<n;i++){
	    if (used[i] && !cused[i] && d > 0 && adj[x][i] == 2){
		if (d - a[i] > 0){
		    a[x]+=a[i];
		    add(i+1, x+1, a[i]);
		    pull(i, a[i]);
		    d-=a[i];
		}else{
		    a[x]+=d;
		    a[i]-=d;
		    add(i+1, x+1, d);
		    d = 0;
		}
	    }
	}
    }

    private void dfs(int x){
	used[x] = true;
	sumA+=a[x];
	sumB+=b[x];
	for(int i=0;i<n;i++){
	    if (!used[i] && adj[x][i] == 1) {
		adj[x][i] = adj[i][x] = 2;
		dfs(i);
	    }
	}
	comp[size++] = x;
    }

    private void add(int f, int t, int a){
	from[yk] = f;
	to[yk] = t;
	amount[yk++] = a;
    }

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


import java.util.List;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
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.util.Collections;
import java.io.InputStream;

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

class TaskE {

    private int vertexCounter, edgeCounter, value;
    private int[] path;
    private long[] initial, desired;
    private List<Integer>[] graph;
    private DSU dsu;
    private List<Integer> more, less;
    private boolean[] ready;
    private List<Transfusion> answer;

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

        vertexCounter = in.nextInt();
        value = in.nextInt();
        edgeCounter = in.nextInt();

        initial = new long[vertexCounter];
        desired = new long[vertexCounter];
        ready = new boolean[vertexCounter];
        more = new ArrayList<Integer>();
        less = new ArrayList<Integer>();
        answer = new ArrayList<Transfusion>();
        graph = new ArrayList[vertexCounter];
        for (int i = 0; i < vertexCounter; ++i)
            graph[i] = new ArrayList<Integer>();

        for (int i = 0; i < vertexCounter; ++i)
            initial[i] = in.nextInt();
        for (int i = 0; i < vertexCounter; ++i)
            desired[i] = in.nextInt();

        dsu = new DSU(vertexCounter, initial, desired);

        int v, u;
        for (int i = 0; i < edgeCounter; ++i) {
            v = in.nextInt() - 1;
            u = in.nextInt() - 1;
            graph[u].add(v);
            graph[v].add(u);
            dsu.union(v, u);
        }

        if (!dsu.check()) {
            out.println("NO");
            return;
        }

        for (int i = 0; i < vertexCounter; ++i)
            if (initial[i] == desired[i])
                ready[i] = true;
            else if (initial[i] > desired[i])
                more.add(i);
            else
                less.add(i);

        Comparator<Integer> cmp = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(dsu.getSet(o1), dsu.getSet(o2));
            }
        };
        Collections.sort(more, cmp);
        Collections.sort(less, cmp);

        int current = 0;
        for (int i = 0; i < more.size(); ++i)
            if (initial[more.get(i)] - desired[more.get(i)] > desired[less.get(current)] - initial[less.get(current)]) {
                transfusion(more.get(i), less.get(current), (int) (desired[less.get(current)] - initial[less.get(current)]));
                ready[less.get(current)] = true;
                current++;
                i--;
            } else if (initial[more.get(i)] - desired[more.get(i)] < desired[less.get(current)] - initial[less.get(current)]) {
                transfusion(more.get(i), less.get(current), (int) (initial[more.get(i)] - desired[more.get(i)]));
                ready[more.get(i)] = true;
            } else {
                transfusion(more.get(i), less.get(current), (int) (initial[more.get(i)] - desired[more.get(i)]));
                ready[more.get(i)] = true;
                ready[less.get(current)] = true;
                current++;
            }

        out.println(answer.size());
        for (Transfusion transfusion : answer)
            transfusion.println(out);
    }

    private void transfusion(int from, int to, int delta) {
        path = new int[vertexCounter];
        Arrays.fill(path, -1);
        bfs(to, from);
        flow(from, to, delta);
    }

    private void bfs(int start, int finish) {
        int[] queue = new int[vertexCounter];
        int size = 0;
        int next = 0;
        queue[size++] = start;
        while (next < size) {
            int v = queue[next++];
            for (int u : graph[v])
                if (path[u] == -1) {
                    path[u] = v;
                    if (u == finish)
                        return;
                    queue[size++] = u;
                }
        }
    }

    private void flow(int from, int to, int delta) {
        if (from == to)
            return;
        if (initial[path[from]] + delta <= value) {

            answer.add(new Transfusion(from, path[from], delta));
                initial[from] -= delta;
                initial[path[from]] += delta;

            flow(path[from], to, delta);
        } else if (path[from] >= delta) {
            flow(path[from], to, delta);

            answer.add(new Transfusion(from, path[from], delta));
                initial[from] -= delta;
                initial[path[from]] += delta;
        } else {
            int difference = (int) (delta - initial[path[from]]);

            answer.add(new Transfusion(from, path[from], difference));
                initial[from] -= difference;
                initial[path[from]] += difference;

            flow(path[from], to, delta);

            answer.add(new Transfusion(from, path[from], delta - difference));
                initial[from] -= delta - difference;
                initial[path[from]] += delta - difference;
        }
    }

}

class DSU {

    public int[] parent, rank;
    private long[] initial, desired;

    public DSU (int size, long[] initial, long[] desired) {
        parent = new int[size];
        rank = new int[size];
        this.initial = Arrays.copyOf(initial, initial.length);
        this.desired = Arrays.copyOf(desired, desired.length);
        for (int i = 0; i < size; ++i)
            parent[i] = i;
        for (int i = 0; i < size; ++i) {
            this.initial[getSet(i)] += initial[i];
            this.desired[getSet(i)] += desired[i];
        }
    }

    public int getSet(int v) {
        if (parent[v] == v)
            return v;
        return parent[v] = getSet(parent[v]);
    }

    public void union(int v, int u) {
        int a = getSet(v);
        int b = getSet(u);
        if (a != b) {
            if (rank[a] < rank[b]) {
                a ^= b;
                b ^= a;
                a ^= b;
            }
            parent[b] = a;
            if (rank[a] == rank[b])
                ++rank[a];
        }
    }

    public boolean check() {
        for (int v = 0; v < initial.length; ++v) {
            int p = getSet(v);
            if (p != v) {
                initial[p] += initial[v];
                desired[p] += desired[v];
                initial[v] = 0;
                desired[v] = 0;
            }
        }
        for (int i = 0; i < initial.length; ++i)
            if (initial[i] != desired[i])
                return false;
        return true;
    }

}

class Transfusion {

    public int from, to, value;

    public Transfusion(int x, int y, int v) {
        from = x;
        to = y;
        value = v;
    }

    public void println(PrintWriter out) {
        out.print(from + 1);
        out.print(" ");
        out.print(to + 1);
        out.print(" ");
        out.println(value);
    }

}

class InputReader {

    private static BufferedReader bufferedReader;
    private static StringTokenizer stringTokenizer;

    public InputReader(InputStream inputStream) {
        bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        stringTokenizer = null;
    }

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

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

    }


import java.util.List;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
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.util.Collections;
import java.io.InputStream;

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

class TaskE {

    private int vertexCounter, edgeCounter, value;
    private int[] path;
    private long[] initial, desired;
    private List<Integer>[] graph;
    private DSU dsu;
    private List<Integer> more, less;
    private boolean[] ready;
    private List<Transfusion> answer;

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

        vertexCounter = in.nextInt();
        value = in.nextInt();
        edgeCounter = in.nextInt();

        initial = new long[vertexCounter];
        desired = new long[vertexCounter];
        ready = new boolean[vertexCounter];
        more = new ArrayList<Integer>();
        less = new ArrayList<Integer>();
        answer = new ArrayList<Transfusion>();
        graph = new ArrayList[vertexCounter];
        for (int i = 0; i < vertexCounter; ++i)
            graph[i] = new ArrayList<Integer>();

        for (int i = 0; i < vertexCounter; ++i)
            initial[i] = in.nextInt();
        for (int i = 0; i < vertexCounter; ++i)
            desired[i] = in.nextInt();

        dsu = new DSU(vertexCounter, initial, desired);

        int v, u;
        for (int i = 0; i < edgeCounter; ++i) {
            v = in.nextInt() - 1;
            u = in.nextInt() - 1;
            graph[u].add(v);
            graph[v].add(u);
            dsu.union(v, u);
        }

        if (!dsu.check()) {
            out.println("NO");
            return;
        }

        for (int i = 0; i < vertexCounter; ++i)
            if (initial[i] == desired[i])
                ready[i] = true;
            else if (initial[i] > desired[i])
                more.add(i);
            else
                less.add(i);

        Comparator<Integer> cmp = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(dsu.getSet(o1), dsu.getSet(o2));
            }
        };
        Collections.sort(more, cmp);
        Collections.sort(less, cmp);

        int current = 0;
        for (int i = 0; i < more.size(); ++i)
            if (initial[more.get(i)] - desired[more.get(i)] > desired[less.get(current)] - initial[less.get(current)]) {
                transfusion(more.get(i), less.get(current), (int) (desired[less.get(current)] - initial[less.get(current)]));
                ready[less.get(current)] = true;
                current++;
                i--;
            } else {
                transfusion(more.get(i), less.get(current), (int) (initial[more.get(i)] - desired[more.get(i)]));
                ready[more.get(i)] = true;
            }

        out.println(answer.size());
        for (Transfusion transfusion : answer)
            transfusion.println(out);
    }

    private void transfusion(int from, int to, int delta) {
        path = new int[vertexCounter];
        Arrays.fill(path, -1);
        bfs(to, from);
        flow(from, to, delta);
    }

    private void flow(int from, int to, int delta) {
        if (from == to)
            return;
        if (initial[path[from]] + delta <= value) {

            answer.add(new Transfusion(from, path[from], delta));
                initial[from] -= delta;
                initial[path[from]] += delta;

            flow(path[from], to, delta);
        } else if (path[from] >= delta) {
            flow(path[from], to, delta);

            answer.add(new Transfusion(from, path[from], delta));
                initial[from] -= delta;
                initial[path[from]] += delta;
        } else {
            int difference = (int) (delta - initial[path[from]]);

            answer.add(new Transfusion(from, path[from], difference));
                initial[from] -= difference;
                initial[path[from]] += difference;

            flow(path[from], to, delta);

            answer.add(new Transfusion(from, path[from], delta - difference));
                initial[from] -= delta - difference;
                initial[path[from]] += delta - difference;
        }
    }

    private void bfs(int start, int finish) {
        int[] queue = new int[vertexCounter];
        int size = 0;
        int next = 0;
        queue[size++] = start;
        while (size > 0) {
            int v = queue[next++];
            for (int u : graph[v])
                if (path[u] == -1) {
                    path[u] = v;
                    if (u == finish)
                        return;
                    queue[size++] = u;
                }
        }
    }

}

class DSU {

    public int[] parent, rank;
    private long[] initial, desired;

    public DSU (int size, long[] initial, long[] desired) {
        parent = new int[size];
        rank = new int[size];
        this.initial = Arrays.copyOf(initial, initial.length);
        this.desired = Arrays.copyOf(desired, desired.length);
        for (int i = 0; i < size; ++i)
            parent[i] = i;
        for (int i = 0; i < size; ++i) {
            this.initial[getSet(i)] += initial[i];
            this.desired[getSet(i)] += desired[i];
        }
    }

    public int getSet(int v) {
        if (parent[v] == v)
            return v;
        return parent[v] = getSet(parent[v]);
    }

    public void union(int v, int u) {
        int a = getSet(v);
        int b = getSet(u);
        if (a != b) {
            if (rank[a] < rank[b]) {
                a ^= b;
                b ^= a;
                a ^= b;
            }
            parent[b] = a;
            if (rank[a] == rank[b])
                ++rank[a];
        }
    }

    public boolean check() {
        for (int v = 0; v < initial.length; ++v) {
            int p = getSet(v);
            if (p != v) {
                initial[p] += initial[v];
                desired[p] += desired[v];
                initial[v] = 0;
                desired[v] = 0;
            }
        }
        for (int i = 0; i < initial.length; ++i)
            if (initial[i] != desired[i])
                return false;
        return true;
    }

}

class Transfusion {

    public int from, to, value;

    public Transfusion(int x, int y, int v) {
        from = x;
        to = y;
        value = v;
    }

    public void println(PrintWriter out) {
        out.print(from + 1);
        out.print(" ");
        out.print(to + 1);
        out.print(" ");
        out.println(value);
    }

}

class InputReader {

    private static BufferedReader bufferedReader;
    private static StringTokenizer stringTokenizer;

    public InputReader(InputStream inputStream) {
        bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        stringTokenizer = null;
    }

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

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

    }


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

public class Main{

    BufferedReader in;
    StringTokenizer str = null;
    PrintWriter out;

    private String next() throws Exception{
    	if (str == null || !str.hasMoreElements())
    	    str = new StringTokenizer(in.readLine());
    	return str.nextToken();
    }

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

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

    int n, e;
    long V;

    int [][]g;
    long []a, b, amount;
    boolean used[];

    long total = 0;
    int size = 0, yk = 0;
    int []comp, prev;

    int []from, to;
    public void run() throws Exception{
    	in = new BufferedReader(new InputStreamReader(System.in));
    	out = new PrintWriter(System.out);

	n = nextInt();
	V = nextLong();
	e = nextInt();

	a = new long[n];
	for(int i=0;i<n;i++){
	    a[i] = nextLong();
	}
	b = new long[n];
	for(int i=0;i<n;i++){
	    b[i] = nextLong();
	}

	from = new int[2*n*n];
	to = new int[2*n*n];
	amount = new long[2*n*n];

	g = new int[n][n];
	for(int i=0;i<e;i++){
	    int x = nextInt()-1, y = nextInt()-1;
	    g[x][y] = g[y][x] = 1;
	}

	comp = new int[n];
	prev = new int[n];
	Arrays.fill(prev, -1);
	used = new boolean[n];
	boolean ok  =true;

	for(int i=0;i<n;i++){
	    if (!used[i]){
		size = 0;
		total = 0;
		dfs(i);
		if (total != 0){
		    ok = false;
		    break;
		}

		for(int j=0;j<size;j++){
		    int v = comp[j];
		    if (a[v] <= b[v]) continue;
		    parents(v);
		    int u = -1;
		    for(int k=0;k<size;k++){
			int t = comp[k];
			if (a[t] < b[t]){
			    u = t;
			    break;
			}
		    }
		    long d = Math.min(a[v] - b[v], b[u] - a[u]);
		    pour(v, u, d);
		}
	    }
	}

	if (!ok){
	    out.println("NO");
	}else{
	    out.println(yk);
	    for(int i=0;i<yk;i++){
		out.println(from[i] + " " + to[i] + " " + amount[i]);
	    }
	}
	out.close();
    }

    private void pour(int s, int t, long d){
	if (s == t) return;
	int parent = prev[t];

	long x = Math.min(d, a[parent]);
	add(parent, t, x);
	pour(s, parent, d);
	add(parent, t, d-x);
    }

    private void add(int s, int t, long d){
	if (d == 0) return;
	from[yk] = s+1;
	to[yk] = t+1;
	amount[yk++] = d;
	a[s]-=d;
	a[t]+=d;
    }

    private void parents(int x){
	for(int i=0;i<n;i++){
	    if (prev[i] < 0 && g[x][i] == 1) {
		prev[i] = x;
		parents(i);
	    }
	}
    }

    private void dfs(int x){
	used[x] = true;
	total+=a[x] - b[x];

	for(int i=0;i<n;i++){
	    if (!used[i] && g[x][i] == 1){
		dfs(i);
	    }
	}
	comp[size++] = x;
    }

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


import java.util.Scanner;

public class CodeForces1April2019F {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        int res = 0;
        for (char ch : s.toCharArray()) {
            res += isStraight(ch);
        }
        System.out.println(res % s.length() == 0 ? "YES" : "NO");
    }

    private static int isStraight(char ch) {
        switch (ch) {
            case 'A':
            case 'E':
            case 'F':
            case 'H':
            case 'I':
            case 'K':
            case 'L':
            case 'M':
            case 'N':
            case 'T':
            case 'V':
            case 'W':
            case 'X':
            case 'Y':
            case 'Z':
                return 1;
        }
        return 0;
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.IOException;
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;
    InputReader in = new InputReader(inputStream);
    PrintWriter out = new PrintWriter(outputStream);
    TaskF solver = new TaskF();
    solver.solve(1, in, out);
    out.close();
  }

  static class TaskF {
    public void solve(int testNumber, InputReader in, PrintWriter out) {
      String s = in.readString();
//    "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//    String straightLetters = "ABCDEFGHIJKMNOPQRSTUVWXZ";
      String straightLetters = "AEFHIKLMNTVWXYZ";

      int numStraight = 0;
      for (char c : s.toCharArray()) {
        if (straightLetters.contains("" + c)) {
          numStraight++;
        }
      }
      out.println(numStraight == 0 || numStraight == s.length() ? "YES" : "NO");
    }

  }

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

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

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

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

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

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

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

    }

  }
}


import java.util.Scanner;

public class NeatWords {

	public static void main(String[] args) {

		Scanner scan = new Scanner(System.in);
		String str;
		char myArray[];
		int len, nC, cC;
		nC = 0;
		cC = 0;
		str = scan.nextLine();
		str = str.toUpperCase();
		len = str.length();
		char lin[] = { 'A', 'E', 'F', 'H', 'I', 'M', 'L', 'N', 'T', 'V', 'X', 'Z', 'W', 'K','Y' };
		char nonLin[] = { 'B', 'C', 'D', 'G', 'J', 'O', 'P', 'Q', 'R', 'S', 'U' };

		myArray = new char[len];
		for (int i = 0; i < len; i++) {
			myArray[i] = str.charAt(i);

			for (int j = 0; j < lin.length; j++) {
				if (myArray[i] == lin[j]) {
					nC++;
				}
			}
			for (int k = 0; k < nonLin.length; k++) {
				if (myArray[i] == nonLin[k]) {
					cC++;
				}
			}
		}

		if (nC == str.length() || cC == str.length()) {
			System.out.println("YES");
		} else {
			System.out.println("NO");
		}
		scan.close();

	}

}


import java.util.Scanner;

public class NeatWords {
	public static void main(String[] args) {
		String lined = "AEFHIKLMNTVWXYZ";
		Scanner scan = new Scanner(System.in);
		String word = scan.nextLine();
		int sum = lined.indexOf(word.charAt(0))!=-1 ? 1 : 0;
		boolean yes = true;
		for(int i = 1; i < word.length(); i++) {
			if(lined.indexOf(word.charAt(i))!=-1) {
				if(sum == 0) {
					yes = false;
					break;
				}
				sum++;
			}else {
				if(sum != 0) {
					yes = false;
					break;
				}
			}
		}
		System.out.println(yes?"YES":"NO");
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.util.*;

import static java.lang.Math.*;

public class Main {
    ArrayList<Integer> g[];
    HashSet<Integer> from[];
    Queue<Integer> q = new ArrayDeque<>();
    boolean used[];
    int[] dist;

    void bfs() {
        while (!q.isEmpty()) {
            int v = q.poll();
            for (Integer to : g[v]) {
                if (!used[to]) {
                    used[to] = true;
                    dist[to] = dist[v] + 1;
                    q.add(to);
                }
                if (dist[to] == dist[v] + 1) from[to].add(v);
            }
        }
    }

    void run() throws IOException {
        int n = nextInt();
        int m = nextInt();
        used = new boolean[n];
        dist = new int[n];
        g = new ArrayList[n];
        from = new HashSet[n];
        for (int i = 0; i < n; i++) {
            g[i] = new ArrayList<>();
            from[i] = new HashSet<>();
        }
        for (int i = 0; i < m; i++) {
            int u = nextInt() - 1;
            int v = nextInt() - 1;
            g[v].add(u);
        }
        int k = nextInt();
        int[] p = new int[k];
        for (int i = 0; i < k; i++) {
            p[i] = nextInt() - 1;
        }
        used[p[k - 1]] = true;
        q.add(p[k - 1]);
        bfs();
        int min = 0;
        int max = 0;
        for (int i = 0; i < p.length - 1; i++) {
            int v = p[i];
            if (from[p[i]].contains(p[i + 1])) {
                if (from[p[i]].size() > 1) max++;
            } else {
                min++;
                max++;
            }
        }
        pw.print(min + " " + max);
        pw.close();
    }

    static BufferedReader br;
    static StringTokenizer st = new StringTokenizer("");
    static PrintWriter pw;

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

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

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

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

    public static void main(String[] args) throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in));
        pw = new PrintWriter(System.out);
        new Main().run();
    }

}


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

public class A {
    static class Parser{
        private BufferedReader bf;
        private StringTokenizer st;

        Parser(){
            bf = new BufferedReader(new InputStreamReader(System.in));
        }

        Parser(int a) throws FileNotFoundException {
            bf = new BufferedReader(new FileReader("input.txt"));
        }

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

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

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

    static Parser in;
    static PrintWriter out;

    static int n, m;

    static class pair{
        int f, s;

        public pair(int f, int s) {
            this.f = f;
            this.s = s;
        }
    }

    static class pr{
        int f;
        ArrayList<Integer> s;

        public pr(int f, int ... e) {
            this.f = f;

            s = new ArrayList<>(e.length);
            for (int i = 0; i < e.length; i++) s.add(e[i]);

        }
    }

    static final int MAXN = 200 * 1000 + 1;

    static ArrayList<Integer>[] g = new ArrayList[MAXN];
    static ArrayList<Integer>[] inv_g = new ArrayList[MAXN];
    static int[] root = new int[MAXN];
    static ArrayList<Integer>[] near = new ArrayList[MAXN];

    static int[] dist = new int[MAXN];
    static ArrayList<Integer>[] edges = new ArrayList[MAXN];

    static boolean areRootNeighbours(int a, int b){
        for (int neigh: near[a]) if(neigh == b) return true;
        return false;
    }

    static void bfs(int v){
        boolean[] used = new boolean[MAXN];
        for (int i = 1; i <= n; i++){
            dist[i] = (int)1e8;
            edges[i] = new ArrayList<>();
        }
        dist[v] = 0;

        Queue<pair> que = new LinkedList<>();
        que.add(new pair(v, 1));
        while(!que.isEmpty()){
            pair ww = que.remove();
            v = ww.f;
            int ind = ww.s;

            if(used[v]) continue;
            used[v] = true;

            for(int to: inv_g[v]){
                if(dist[to] > ind + 1){
                    dist[to] = ind + 1;
                    edges[to].add(v);

                }else if(dist[to] == ind + 1){
                    if(areRootNeighbours(to, v)){

                        if(edges[to].isEmpty()) edges[to].add(v);
                        else {
                            int temp = edges[to].get(0);
                            edges[to].set(0, v);
                            if(edges[to].size() < 2) edges[to].add(temp);
                        }
                    }else if(edges[to].size() < 2) edges[to].add(v);
                }

                que.add(new pair(to, ind + 1));
            }
        }
    }

    static void solve() throws IOException {
        n = in.nextInt();
        m = in.nextInt();
        for (int i = 1; i <= n; i++) {
            g[i] = new ArrayList<>();
            inv_g[i] = new ArrayList<>();
            near[i] = new ArrayList<>();
            edges[i] = new ArrayList<>();
        }

        for (int i = 0; i < m; i++) {
            int a = in.nextInt();
            int b = in.nextInt();
            g[a].add(b);
            inv_g[b].add(a);
        }

        int q = in.nextInt();
        for(int i = 0; i < q; ++i) root[i] = in.nextInt();
        for (int i = 0; i < q; i++) {
            if(i > 0) near[root[i]].add(root[i - 1]);
            if(i + 1 < q) near[root[i]].add(root[i + 1]);
        }

        bfs(root[q - 1]);

        int c1 = 0, c2 = 0;
        for(int i = 0; i < q - 1; ++i){
            int pt = root[i];
            int next = root[i + 1];

            boolean isok = false;
            for(int to: edges[pt]){
                if(to == next){
                    isok = true;
                    break;
                }
            }

            if(!isok) ++c1;
            if(!isok || edges[pt].size() > 1) ++c2;
        }

        out.println(c1 + " " + c2);
    }

    public static void main(String[] args) throws IOException {
        Locale.setDefault(Locale.US);
        in = new Parser();
        out = new PrintWriter(System.out);

        solve();

        out.close();
    }
}


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

public class Main {
    static ArrayList<Integer>[] gr, g;
    static TreeMap<Integer, Integer> way;
    static int[] types, dist;
    static int INF = (int) 1e9;

    public static void main(String[] args) {
        FastScanner sc = new FastScanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        int n = sc.nextInt();
        int m = sc.nextInt();
        gr = new ArrayList[n];
        g = new ArrayList[n];
        for (int i = 0; i < n; i++) {
            gr[i] = new ArrayList<>();
            g[i] = new ArrayList<>();
        }
        for (int i = 0; i < m; i++) {
            int from = sc.nextInt() - 1;
            int to = sc.nextInt() - 1;
            gr[from].add(to);
            g[to].add(from);
        }
        int k = sc.nextInt();
        int[] p = new int[k];
        for (int i = 0; i < k; i++)
            p[i] = sc.nextInt() - 1;
        way = new TreeMap<>();
        for (int i = 0; i < k - 1; i++)
            way.put(p[i], p[i + 1]);
        types = new int[n];
        //0 - none
        //1 - +
        //2 - -
        //3 - +-
        dist = new int[n];
        Arrays.fill(dist, INF);
        dist[p[k - 1]] = 0;
        bfs(p[k - 1]);
        int cntMin = 0;
        int cntMax = 0;
        for (int i = 0; i < k - 1; i++) {
            if (types[p[i]] == 2) {
                cntMin++;
                cntMax++;
            }
            if (types[p[i]] == 3)
                cntMax++;
        }
        pw.print(cntMin + " " + cntMax);
        pw.close();
    }

    public static void bfs(int start) {
        ArrayDeque<Pair> bfs = new ArrayDeque<>();
        bfs.add(new Pair(start, -1));
        while(!bfs.isEmpty()){
            int v = bfs.getFirst().v;
            int p = bfs.pollFirst().p;
            for (int to : g[v]) {
                if(dist[to] == INF)
                    bfs.add(new Pair(to, v));
                if (dist[to] > dist[v] + 1) {
                    dist[to] = dist[v] + 1;
                    if (way.containsKey(to) && way.get(to) == v)
                        types[to] = 1;
                    else
                        types[to] = 2;
                } else if (dist[to] == dist[v] + 1) {
                    if (way.containsKey(to) && way.get(to) == v)
                        types[to]++;
                    else {
                        if (types[to] < 2)
                            types[to] += 2;
                    }
                }
            }
        }
    }

    public static boolean isVowel(char a) {
        return a == 'a' || a == 'e' || a == 'u' || a == 'o' || a == 'y';
    }

    public static long binPow(long a, int n) {
        long p = a;
        long res = 1;
        while (n > 0) {
            if (n % 2 == 1)
                res *= p;
            p *= p;
            n /= 2;
        }
        return res;
    }

    public static int gcd(int a, int b) {
        if (a == 0 || b == 0)
            return a + b;
        return gcd(b % a, a);
    }

    public static long gcd(long a, long b) {
        if (a == 0 || b == 0)
            return a + b;
        return gcd(b % a, a);
    }
}

class Pair{
    int v, p;

    public Pair(int v, int p) {
        this.v = v;
        this.p = p;
    }
}
class FastScanner {
    static BufferedReader br;
    static StringTokenizer st = new StringTokenizer("");

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

    public FastScanner(String fileName) throws FileNotFoundException {
        br = new BufferedReader(new FileReader(fileName));
    }

    public boolean hasNext() {
        try {
            while (!st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

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

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

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

    public String next() {
        hasNext();
        return st.nextToken();
    }
}


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

import static java.lang.Math.*;

public class Main {
    static ArrayList<Integer>[] gr, g;
    static TreeMap<Integer, Integer> way;
    static int[] types, dist;
    static boolean[] used;
    static int INF = (int) 1e9;

    public static void main(String[] args) {
        FastScanner sc = new FastScanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        int n = sc.nextInt();
        int m = sc.nextInt();
        gr = new ArrayList[n];
        g = new ArrayList[n];
        for (int i = 0; i < n; i++) {
            gr[i] = new ArrayList<>();
            g[i] = new ArrayList<>();
        }
        for (int i = 0; i < m; i++) {
            int from = sc.nextInt() - 1;
            int to = sc.nextInt() - 1;
            gr[from].add(to);
            g[to].add(from);
        }
        int k = sc.nextInt();
        int[] p = new int[k];
        for (int i = 0; i < k; i++)
            p[i] = sc.nextInt() - 1;
        way = new TreeMap<>();
        for (int i = 0; i < k - 1; i++)
            way.put(p[i], p[i + 1]);
        types = new int[n];
        //0 - none
        //1 - +
        //2 - -
        //3 - +-
        used = new boolean[n];
        dist = new int[n];
        Arrays.fill(dist, INF);
        dist[p[k - 1]] = 0;
        dfs(p[k - 1], -1);
        int cntMin = 0;
        int cntMax = 0;
        for (int i = 0; i < k - 1; i++) {
            if (types[p[i]] == 2) {
                cntMin++;
                cntMax++;
            }
            if (types[p[i]] == 3)
                cntMax++;
        }
        pw.print(cntMin + " " + cntMax);
        pw.close();
    }

    public static void dfs(int v, int p) {
        used[v] = true;
        for (int to : g[v]) {
            if (dist[to] > dist[v] + 1) {
                dist[to] = dist[v] + 1;
                if (way.containsKey(to) && way.get(to) == v)
                    types[to] = 1;
                else
                    types[to] = 2;
                dfs(to, v);
            } else if (dist[to] == dist[v] + 1) {
                if (way.containsKey(to) && way.get(to) == v)
                    types[to]++;
                else {
                    if (types[to] < 2)
                        types[to] += 2;
                }
            }
        }
    }

    public static boolean isVowel(char a) {
        return a == 'a' || a == 'e' || a == 'u' || a == 'o' || a == 'y';
    }

    public static long binPow(long a, int n) {
        long p = a;
        long res = 1;
        while (n > 0) {
            if (n % 2 == 1)
                res *= p;
            p *= p;
            n /= 2;
        }
        return res;
    }

    public static int gcd(int a, int b) {
        if (a == 0 || b == 0)
            return a + b;
        return gcd(b % a, a);
    }

    public static long gcd(long a, long b) {
        if (a == 0 || b == 0)
            return a + b;
        return gcd(b % a, a);
    }
}

class chr {
    char a;
    int index;

    public chr(char a, int index) {
        this.a = a;
        this.index = index;
    }
}

class chrComp implements Comparator<chr> {
    public int compare(chr o1, chr o2) {
        return Character.compare(o1.a, o2.a);
    }
}

class FastScanner {
    static BufferedReader br;
    static StringTokenizer st = new StringTokenizer("");

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

    public FastScanner(String fileName) throws FileNotFoundException {
        br = new BufferedReader(new FileReader(fileName));
    }

    public boolean hasNext() {
        try {
            while (!st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

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

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

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

    public String next() {
        hasNext();
        return st.nextToken();
    }
}


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

public class Main {
	static final Integer N = Integer.valueOf(1000010), MOD = Integer.valueOf(1000000007);

	public static Integer mul(Integer x, Integer y) {
		Long ret = Long.valueOf(x.intValue());
		ret = (ret * y) % MOD;
		return Integer.valueOf(ret.intValue());
	}

	public static Integer power(Integer basic, Integer times) {
		Integer ret = Integer.valueOf(1);
		while(times > 0) {
			if((times & 1) == 1) ret = mul(ret, basic);
			basic = mul(basic, basic);
			times >>= 1;
		}
		return ret;
	}

	public static Integer[] extGcd(Integer a, Integer b) {
		Integer [] ret = new Integer[3];
		if(b == 0) {
			ret[0] = Integer.valueOf(a.intValue());
			ret[1] = Integer.valueOf(1);
			ret[2] = Integer.valueOf(0);
		} else {
			Integer [] tmp = extGcd(b, a % b);
			Integer g = tmp[0], ta = tmp[2], tb = tmp[1] - a / b * tmp[2];
			if(ta < 0) {
				Integer t = ta / (b / g);
				ta -= t * (b / g);
				tb += t * (a / g);
			}
			if(ta < 0) {
				ta += b / g;
				tb -= a / g;
			}
			ret[0] = g;
			ret[1] = ta;
			ret[2] = tb;
		}
		return ret;
	}

	public static Integer inv(Integer x) {
//		0-> gcd   1->ta    2->tb
		Integer [] results = extGcd(x, MOD);
		return results[1];
	}

	public static Integer solve(Integer n, Integer m) {
//		System.out.println(n + " " + m);

		Integer [] f = new Integer[m + 3];
		f[0] = Integer.valueOf(0);
		for(Integer i = Integer.valueOf(1); i <= m + 2; i++)
			f[i] = Integer.valueOf((f[i - 1] + power(i, m)) % MOD);
//		System.out.println(power(Integer.valueOf(2), Integer.valueOf(100)));

//		for(Integer i = Integer.valueOf(1); i <= m + 2; i++)
//			System.out.print(f[i] + " ");
//		System.out.println("");

		if(n <= m + 2) return f[n];

		Integer [] lagrange = new Integer[m + 3];
		Integer [] fact = new Integer[m + 3];
		fact[0] = Integer.valueOf(1);
		for(Integer i = Integer.valueOf(1); i <= m + 2; i++)
			fact[i] = mul(fact[i - 1], i);
		for(Integer i = Integer.valueOf(1); i <= m + 2; i++) {
			lagrange[i] = f[i];
			lagrange[i] = mul(lagrange[i], inv(mul(fact[i - 1], fact[m + 2 - i])));
			if(((m + 2 - i) & 1) == 1)
				lagrange[i] = MOD - lagrange[i];
//			System.out.print(lagrange[i] + " ");
		}
//		System.out.println("");

		Integer fullDenominator = Integer.valueOf(1);
		for(Integer i = Integer.valueOf(1); i <= m + 2; i++)
			fullDenominator = mul(fullDenominator, n - i);
//		System.out.println(fullDenominator);

		Integer ret = Integer.valueOf(0);
		for(Integer i = Integer.valueOf(1); i <= m + 2; i++) {
			Integer denominator = Integer.valueOf(mul(fullDenominator, inv(n - i)));
//			System.out.print(denominator + " ");
			ret = (ret + mul(denominator, lagrange[i])) % MOD;
		}
		return ret;
	}

	public static void main(String[] args) throws IOException {
		Scanner reader = new Scanner(System.in);
		Integer n = new Integer(reader.nextInt());
		Integer k = new Integer(reader.nextInt());

		Integer ans = solve(n, k);

		System.out.println(ans);

		reader.close();
	}
}