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.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
 
public  class realfast implements Runnable {
    private static final int INF = (int) 1e9;
 
    public  void solve() throws IOException 
    {
      
     int n = readInt();
     int m = readInt();
     int arr[][]= new int [n][m];
     for(int i =0;i<n;i++)
     {
      for(int j =0;j<m;j++)
      {
       arr[i][j]= readInt();	
      }	
     }
     int left =0;
     int right =1000000000;
     
     int fin1=0;
     int fin2=0;
     int ans=0;
     while(left<=right)
     {
     	int mid = left+(right-left)/2;
        int x[]= new int[2];
        x[0]=-1;
        x[1]=-1;
     	dojob(arr,mid,x);
     	if((x[0]!=-1)&&(x[1]!=-1))
     	{
     		fin1=x[0];
     		fin2=x[1];
     		left=mid+1;
     		ans=mid;
     	}
     	else
     	{
     		right=mid-1;
     	}

        
     }
   
     out.println((fin1+1)+" "+(fin2+1));
    }
    public void dojob(int arr[][], int del , int x[])
    {
    	int n = arr.length;
    	int m = arr[0].length;
    	int pow = (int)Math.pow(2,m);
    	pow--;
    	int dp[] = new int[256];
    	Arrays.fill(dp,-1);
    	dp[0]=0;
    	for(int i=0;i<arr.length;i++)
    	{
    	 int val=0;
    	 int cal=1;
    	 for(int j =0;j<arr[0].length;j++)
    	 {
    	 	if(arr[i][j]>=del)
    	 	{
    	 		val=val+cal;
    	 	}
    	 	cal=2*cal;
    	 }
          if(dp[pow-val]!=-1)
          {
          	x[0]=dp[pow-val];
          	x[1]= i;
          	return ;
          }
          check(dp,val,i);
    	}

    	return ;
    }
    public void check(int dp[], int i, int z)
    {
    	if(dp[i]!=-1)
    	return  ;
    	dp[i]=z;
    	int j=1;
    	while(j<=i)
    	{
    		if((i&j)!=0)
    		check(dp,i-j,z);

    		j=2*j;
    	}
      
    }
    

    
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public static void main(String[] args) {
        new Thread(null, new realfast(), "", 128 * (1L << 20)).start();
    }
 
    private static final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null;
    private BufferedReader reader;
    private StringTokenizer tokenizer;
    private PrintWriter out;
 
    @Override
    public void run() {
        try {
            if (ONLINE_JUDGE || !new File("input.txt").exists()) {
                reader = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(System.out);
            } else {
                reader = new BufferedReader(new FileReader("input.txt"));
                out = new PrintWriter("output.txt");
            }
            solve();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                // nothing
            }
            out.close();
        }
    }
 
    private String readString() throws IOException {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(reader.readLine());
        }
        return tokenizer.nextToken();
    }
 
    @SuppressWarnings("unused")
    private int readInt() throws IOException {
        return Integer.parseInt(readString());
    }
 
    @SuppressWarnings("unused")
    private long readLong() throws IOException {
        return Long.parseLong(readString());
    }
 
    @SuppressWarnings("unused")
    private double readDouble() throws IOException {
        return Double.parseDouble(readString());
    }
}
class edge implements Comparable<edge>{
    int u ;
    int v ;
    int val;
    edge(int u1, int v1 , int val1)
    {
       this.u=u1;
       this.v=v1;
       this.val=val1;
    }
    public int compareTo(edge e)
    {
        return this.val-e.val;
    }
}