Problem: You are given n arrays a_1, a_2, ..., a_n; each array consists of exactly m integers. We denote the y-th element of the x-th array as a_{x, y}.

You have to choose two arrays a_i and a_j (1 ≤ i, j ≤ n, it is possible that i = j). After that, you will obtain a new array b consisting of m integers, such that for every k ∈ [1, m] b_k = max(a_{i, k}, a_{j, k}).

Your goal is to choose i and j so that the value of min _{k = 1}^{m} b_k is maximum possible.

Input

The first line contains two integers n and m (1 ≤ n ≤ 3 ⋅ 10^5, 1 ≤ m ≤ 8) — the number of arrays and the number of elements in each array, respectively.

Then n lines follow, the x-th line contains the array a_x represented by m integers a_{x, 1}, a_{x, 2}, ..., a_{x, m} (0 ≤ a_{x, y} ≤ 10^9).

Output

Print two integers i and j (1 ≤ i, j ≤ n, it is possible that i = j) — the indices of the two arrays you have to choose so that the value of min _{k = 1}^{m} b_k is maximum possible. If there are multiple answers, print any of them.

Example

Input


6 5
5 0 3 1 2
1 8 9 1 3
1 2 3 4 5
9 1 0 3 7
2 3 0 6 3
6 4 1 7 0


Output


1 5

Solution (in JAVA):

Solution:
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.BitSet;
import java.util.InputMismatchException;
import java.util.PriorityQueue;

public class d {
/*
6 6
1 1 1 1 1 1
2 2 2 2 2 2
3 3 3 3 3 3
4 4 4 4 4 4
5 5 5 5 5 5
6 6 6 6 6 6

1 6
6 6 6 6 6 6

 */
	static class Solver {
		
		int N, M, arrs[][];
		
		BitSet over[];
		void setup(int min) {
			for(int idx = 0, bb = 1; idx < M; idx++, bb <<= 1) {
				over[bb].clear();
				for(int a = 0; a < N; a++)
					if(arrs[idx][a] >= min)
						over[bb].set(a);
			}
			for(int mask = 1; mask < 1 << M; mask++) {
				if(Integer.bitCount(mask) == 1) continue;
				int lo = mask & (-mask), rm = mask - lo;
				over[mask].clear();
				over[mask].or(over[lo]);
				over[mask].and(over[rm]);
			}
		}
		
		boolean canDo(int lim) {
			setup(lim);
			
			for(int i = 0; i < N; i++) {
				int need = 0;
				for(int b = 0, bb = 1; b < M; b++, bb <<= 1)
					if(arrs[b][i] < lim)
						need += bb;
				if(over[need].cardinality() > 0) {
					can = new int[] { i + 1, over[need].nextSetBit(0) + 1 };
					return true;
				}
			}
			return false;
		}
		
		int can[];
		PriorityQueue<Integer> vq = new PriorityQueue<>();
		
		void solve(FastScanner s, PrintWriter out) {
			N = s.nextInt(); M = s.nextInt();
			Arrays.setAll(over = new BitSet[1 << M], x -> new BitSet());
			over[0].set(0, N, true);
			
			arrs = new int[M][N];
			for(int a = 0; a < N; a++)
				for(int p = 0; p < M; p++)
					vq.add(arrs[p][a] = s.nextInt());
			
			// list to maintain unique array values
			IntList IL = new IntList();
			int last = -1, cur;
			while(!vq.isEmpty()) {
				cur = vq.poll();
				if(cur == last) continue;
				IL.add(last = cur);
			}

			// binary search IL to find limiting answer
			int m, lo = 0, hi = IL.size() - 1;
			int a = -1, b = -1;
			while(lo <= hi) {
				m = lo + (hi - lo) / 2;
				if(canDo(IL.get(m))) {
					a = can[0]; b = can[1];
					lo = m + 1;
				} else {
					hi = m - 1;
				}
			}
			out.printf("%d %d%n", a, b);
		}
		
		static class IntList {
			static int[] EMPTY = {};
			int n = 0, a[] = EMPTY;
			void add(int v) {
				if (n >= a.length)
					a = Arrays.copyOf(a, (n << 2) + 8);
				a[n++] = v;
			}
			int get(int idx) { return a[idx]; }
			int size() { return n; }
		}
		
	}
	
	public static void main(String[] args) {
		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		new Solver().solve(s, out);
		out.close(); s.close();
	}
	
	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1 << 22];
		private int curChar;
		private int numChars;
		
		public FastScanner(InputStream stream) {
			this.stream = stream;
		}
		
		public FastScanner(File f) throws FileNotFoundException {
			this(new FileInputStream(f));
		}
		
		public FastScanner(String s) {
			this.stream = new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8));
		}
		
		void close() {
			try {
				stream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		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;
		}
		
		public int nextInt() {
			return Integer.parseInt(next());
		}
		
		public long nextLong() {
			return Long.parseLong(next());
		}
		
		public double nextDouble() {
			return Double.parseDouble(next());
		}
		
		public 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();
		}
		
		public 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();
		}
		
		public int[] nextIntArray(int N) {
			int[] ret = new int[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextInt();
			return ret;
		}
		
		public int[][] next2DIntArray(int N, int M) {
			int[][] ret = new int[N][];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextIntArray(M);
			return ret;
		}
		
		public long[] nextLongArray(int N) {
			long[] ret = new long[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextLong();
			return ret;
		}
		
		public long[][] next2DLongArray(int N, int M) {
			long[][] ret = new long[N][];
			for (int i = 0; i < N; i++)
				ret[i] = nextLongArray(M);
			return ret;
		}
		
		public double[] nextDoubleArray(int N) {
			double[] ret = new double[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextDouble();
			return ret;
		}
		
		public double[][] next2DDoubleArray(int N, int M) {
			double[][] ret = new double[N][];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextDoubleArray(M);
			return ret;
		}
		
	}
	
}