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.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class EducationalRound80D {

	public static void solve() {
		int n=s.nextInt();
		int m=s.nextInt();
		int[][] arr = new int[n][m];
//		if(n==1) {
//			out.println(1 + " "+1);
//			return;
//		}
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				arr[i][j]=s.nextInt();
			}
		}
		int val = bs(arr);
//		out.println(val);
		int[] mask = new int[1<<m];
		for(int i = 0;i<arr.length;i++) {
			int curr_mask=0;
			for(int j=0;j<arr[i].length;j++) {
				if(val<=arr[i][j]) {
					curr_mask^=(1<<j);
				}
			}
			mask[curr_mask]=i+1;
		}
		for(int i=0;i<(1<<m);i++) {
			if(mask[i]>0) {
				for(int j=0;j<(1<<m);j++) {
					if(mask[j]>0 && (i|j)==((1<<m)-1)) {
						out.println((mask[i])+" "+(mask[j]));
						return;
					}
				}
			}
		}
 	}
	
	public static int bs(int[][] arr) {
		int start = 0;
		int end = (int)1e9+10;
		int ans = 0;
		while(start<=end) {
			int mid = (start+end)>>1;
			if(check(mid,arr)) {
				start = mid+1;
				ans = mid;
			}else {
				end = mid-1;
			}
		}
		return ans;
	}
	
	public static boolean check(int mid,int [][] arr) {
		int m = arr[0].length;
		int[] mask = new int[1<<m];
		for(int i = 0;i<arr.length;i++) {
			int curr_mask=0;
			for(int j=0;j<arr[i].length;j++) {
				if(mid<=arr[i][j]) {
					curr_mask^=(1<<j);
				}
			}
			mask[curr_mask]=1;
		}
		for(int i=0;i<(1<<m);i++) {
			if(mask[i]>0) {
				for(int j=0;j<(1<<m);j++) {
					if(mask[j]>0 && (i|j)==((1<<m)-1)) {
						return true;
					}
				}
			}
		}
		return false;
	}

	public static void main(String[] args) {
		out = new PrintWriter(new BufferedOutputStream(System.out));
		s = new FastReader();
		solve();
		out.close();
	}

	public static FastReader s;
	public static PrintWriter out;

	public static class FastReader {
		BufferedReader br;
		StringTokenizer st;

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

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

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

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

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

		String nextLine() {
			String str = "";
			try {
				str = br.readLine();
			} catch (Exception e) {
				e.printStackTrace();
			}
			return str;
		}
	}

	
}