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.*;
import java.math.*;

 
 public class Main	{
	 static class tuple{
		 int a, b;
		 long c;
		 public tuple(int a, int b, long c) {this.a = a;this.b = b;this.c = c;}
	 }
   static class Pair implements Comparable<Pair>{

	   int a;
	   long b;
	   int ind;
	   public Pair(int x, long y) {a = x;b=y;}
	   public Pair(int x, int y) {a = x;ind=y;}
	   public Pair(int x,int y, int z){a=x;b=y;ind = z;}
	   public int compareTo(Pair p){
		   return p.a - a;
	   }
//		@Override
//		public int hashCode() {
//			final int prime = 31;
//			int result = 1;
//			result = prime * result + a;
//			result = prime * result + b;
//		   
//			return result;
//		}
//		@Override
//		public boolean equals(Object obj) {
//			Pair cur = (Pair)obj;
//			if((a==cur.a && b==cur.b))return true;
//			return false;
//		}
 }
  static class cell{
	  int a, b;
	  public cell(int x, int y) {
		  a = x;
		  b = y;
	  }
  }
static class TrieNode{
	TrieNode left, right;
	int cnt;
	public TrieNode() {
		cnt = 0;
	}
}
  public static int gcd(int a,int b)
  {
    if(a<b)
      return gcd(b,a);
    if(b==0)
      return a;
    return gcd(b,a%b);
    
  }
  static int lcm(int a,int b) {
	  return  a*b / (int)gcd(a,b);
  }
  
   
    public static void main(String[] args) throws Exception {
       new Thread(null, null, "Anshum Gupta", 99999999) {
            public void run() {
                try {
                    solve();
                } catch(Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }

static long pow(long x,long y){
    if(y == 0)return 1;
    if(y==1)return x;
    long a = pow(x,y/2);
    a = (a*a)%mod;
    if(y%2==0){
        return a;
    }
    return (a*x)%mod;
}

static final long mxx = (long)(1e18+5);
static final int mxN = (int)(1e5 + 5);
static final int mxV = (int)(2e5);
static final long mod = (long)(1e9+7); //998244353;//
static long[]fact,inv_fact;
static long my_inv(long a) {
	return pow(a,mod-2);
}
static long bin(int a,int b) {
	if(a < b || a<0 || b<0)return 0;
    return ((fact[a]*inv_fact[a-b])%mod * inv_fact[b])%mod;
}
	
static void make_facts() {
  fact=new long[mxN];
  inv_fact = new long[mxN];
  fact[0]=inv_fact[0]=1L;
  for(int i=1;i<mxN;i++) {
	   fact[i] = (i*fact[i-1])%mod;
	   inv_fact[i] = my_inv(fact[i]);
  }
}
static void lazy(int st, int e, int tn) {
	if(lazy[tn] != INF) {
		tree[tn] = Math.min(tree[tn], lazy[tn]);
		if(st != e) {
			lazy[2*tn] = Math.min(lazy[2*tn], lazy[tn]);
			lazy[2*tn+1] = Math.min(lazy[2*tn+1], lazy[tn]);
		}
		lazy[tn] = INF;
	}
}
static void update(int ind, int val, int st, int e, int tn) {
	if(st == e) {
		tree[tn] = val;
		return;
	}
	int mid = (st + e) >> 1;	
  	if(ind <= mid)
		update(ind, val, st, mid, 2*tn);
  	else
		update(ind, val, mid+1, e, 2*tn+1);
	tree[tn] = Math.min(tree[2*tn], tree[2*tn+1]);
}
static int query(int l, int r, int st, int e, int tn) {
	if(st > r || e < l)return INF;
	
	if(st >= l && e <= r) {
		return tree[tn];
	}

	int mid = (st + e) >> 1;
	int x = query(l, r, st, mid, 2 * tn);
	int y = query(l, r, mid+1, e, 2 * tn + 1);
	return Math.min(x, y);
}
static int[]tree, lazy;
static final int INF = (int)1e9+5;
static ArrayList<ArrayList<Pair>> adj;
static boolean[]vis;
static int n, m, q, a1, a2;
static int[][]a;
static boolean can(int x) {
	int[]mask = new int[(1<<m)];
	Arrays.fill(mask, -1);
	for(int i=0; i<n; i++) {
		int cur = 0;
		for(int j=0;j<m;j++) {
			if(a[i][j] >= x) {
				cur ^= (1<<j);
			}
			mask[cur] = i;
		}
	}
	if(mask[(1<<m) - 1] != -1) {
		a1 = a2 = mask[(1<<m) - 1];
		return true;
	}
	for(int i=0; i < (1<<m); i++) {
		for(int j=0; j < (1<<m); j++) {
			if(mask[i] != -1 && mask[j] != -1 &&  (i | j) == (1<<m) - 1 ) {
				a1 = mask[i];
				a2 = mask[j];
				return true;
			}
		}
	}
	return false;
}
 public static void solve() throws Exception {
   // solve the problem here
   MyScanner s = new MyScanner();
        out = new PrintWriter(new BufferedOutputStream(System.out), true);
        int tc = 1;//s.nextInt();
        
//	        make_facts(); 
        
        while(tc-->0){
        	n = s.nextInt();
        	m = s.nextInt();
        	a = new int[n][m];
        	for(int i=0;i<n;i++) {
        		for(int j=0;j<m;j++) {
        			a[i][j] = s.nextInt();
        		}
        	}
        	int l = 0, r = INF, ans = 0;
        	while(l <= r) {
        		int mid = (l + r)>>1;
        		if(can(mid)) {
        			ans = mid;
        			l = mid + 1;
        		}
        		else r = mid - 1;
        	}
        }
        a1++;
        a2++;
        out.println(a1 + " " + a2);
        	
           
        out.flush();
}
 
     
 
 
 
    //-----------PrintWriter for faster output---------------------------------
    public static PrintWriter out;
 
    //-----------MyScanner class for faster input----------
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
 
        public MyScanner() {
            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()); }
         
        String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
    //--------------------------------------------------------
}