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.*;
/**
  * Built using my Brain
  * Actual solution is at the bottom
  *
  * @author Lenard Hoffstader
*/

public class cfjava
{
  public static void main(String[] args)
  {
    OutputStream outputStream = System.out;
    FastReader in = new FastReader();
    PrintWriter out = new PrintWriter(outputStream);
    PROBLEM solver = new PROBLEM();
    int t=1;
    // t=in.nextInt();
    for(int i=0;i<t;i++){
      solver.solve(in, out);
    }
    out.close();
  }

  static class PROBLEM
  {
    long mat[][];
    int idx1,idx2,n,m;
    public void solve(FastReader in,PrintWriter out)
    {
      n = in.nextInt();m = in.nextInt();
      mat = new long[n][m];
      for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
          mat[i][j] = in.nextLong();
        }
      }
      idx1=idx2=-1;
      long l=0,r=(long)1e9,mid=0;
      long val=0;
      while(l<=r){
        mid=(l+r)/2;
        if(possat(mid)){
          l=mid+1;
          val=mid;
        }
        else r=mid-1;
      }
      possat(val);
      out.println(idx1+" "+idx2);
    }
    boolean possat(long x)
    {
      // operation means selecting 2 rows taking max of ai and bi
      // and ans here means min of resultant row
      int mask[] = new int[n];
      Arrays.fill(mask,0);
      // if 1 that means >=x and then if we take any 2 masks and their OR is all 1s
      // means there exists two rows whose operation value has atleast x as ans
      HashMap<Integer,Boolean> mp = new HashMap<>();
      ArrayList<pair<Integer,Integer> > arr = new ArrayList<>();
      for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
          if(mat[i][j]>=x){mask[i]|=(1<<j);}
        }
        if(!mp.containsKey(mask[i])){
          mp.put(mask[i], true);
          arr.add(new pair(mask[i],i));
        }
      }
      int value = (1<<m)-1;
      for(int i=0;i<arr.size();i++){
        for(int j=i;j<arr.size();j++){
          if((arr.get(i).x|arr.get(j).x)== value){
            idx1=arr.get(i).y+1;
            idx2=arr.get(j).y+1;
            return true;
          }
        }
      }
      return false;
    }
  }
  static class pair<U extends Comparable<U>, V extends Comparable<V>> implements Comparable<pair<U, V>>
  {
    public U x;
    public V y;

    public pair(U x, V y) {
      this.x = x;
      this.y = y;
    }

    public int compareTo(pair<U, V> other) {
      int i = x.compareTo(other.x);
      if (i != 0) return i;
      return y.compareTo(other.y);
    }

    public String toString() {
      return x.toString() + " " + y.toString();
    }

    public boolean equals(Object obj){
      if (this.getClass() != obj.getClass()) return false;
      pair<U, V> other = (pair<U, V>) obj;
      return x.equals(other.x) && y.equals(other.y);
    }
    public int hashCode(){
      return 31 * x.hashCode() + y.hashCode();
    }
  }
  static class FastReader 
  {
    BufferedReader br; 
    StringTokenizer st;

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

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

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

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

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

    boolean nextBoolean(){
      if(nextInt()==1)return true;
      else return false;
    }
    // boolean nextBoolean(){return Boolean.parseBoolean(next());}

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