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.*;
import java.util.*;
 
public class Solution {
     
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(System.out);
          
          StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		
		int[][] a = new int[n][m];
		
		for(int i=0;i<n;i++){
		   st = new StringTokenizer(br.readLine());
		    for(int j=0;j<m;j++)
		     a[i][j] = Integer.parseInt(st.nextToken());
		}
		
		//Arrays.stream(a).forEach(e->System.out.println(Arrays.toString(e)));
		
		int ans = findResult(a);
		
		int[] bits = getBits(a,ans);
		boolean found = false;
		for(int i=0;i<bits.length;i++){
	          if(bits[i] != -1){
	               
	               if(i == bits.length -1)
	                  out.println((bits[i]+1)+" "+(bits[i]+1));
	               
	               for(int j=i+1;j<bits.length;j++){
	                  if(bits[j] != -1 && (i|j) == bits.length -1){
	                      out.println((bits[i]+1)+" "+(bits[j]+1));
	                      found = true;
	                      break;
	                   }
	               }
	               if(found)
	                 break;
	          }
	     }
		
		out.close();
	}
	
	private static int findResult(int[][] a){
	     int low = 0, high = 1000000000;
	     
	     while(low < high){
	          int mid = (low+high+1)/2;
	          int[] bits = getBits(a,mid);
	          
	          if(isPossible(bits))
	            low = mid;
	          else
	            high = mid-1;
	     }
	     
	     return low;
	}
	
	private static int[] getBits(int[][] a, int val){
	     int m = a[0].length;
	     int[] bits = new int[1<<m];
	     Arrays.fill(bits,-1);
	     
	     for(int i=0;i<a.length;i++){
	          int mask = 0;
	          for(int j=0;j<m;j++){
	               if(a[i][j] >= val)
	                 mask|=(1<<j);
	          }
	           bits[mask] = i;
	     }
	     
	     return bits;
	}
	
	private static boolean isPossible(int[] bits){
	     for(int i=0;i<bits.length;i++){
	          if(bits[i] != -1){
	               
	               if(i == bits.length -1)
	                  return true;
	               
	               for(int j=i+1;j<bits.length;j++)
	                 if(bits[j] != -1 && (i|j) == bits.length -1)
	                     return true; 

	          }
	     }
	     
	     return false;
	}
}