Problem: You are given the set of vectors on the plane, each of them starting at the origin. Your task is to find a pair of vectors with the minimal non-oriented angle between them.

Non-oriented angle is non-negative value, minimal between clockwise and counterclockwise direction angles. Non-oriented angle is always between 0 and π. For example, opposite directions vectors have angle equals to π.

Input

First line of the input contains a single integer n (2 ≤ n ≤ 100 000) — the number of vectors.

The i-th of the following n lines contains two integers xi and yi (|x|, |y| ≤ 10 000, x2 + y2 > 0) — the coordinates of the i-th vector. Vectors are numbered from 1 to n in order of appearing in the input. It is guaranteed that no two vectors in the input share the same direction (but they still can have opposite directions).

Output

Print two integer numbers a and b (a ≠ b) — a pair of indices of vectors with the minimal non-oriented angle. You can print the numbers in any order. If there are many possible answers, print any.

Examples

Input

4
-1 0
0 -1
1 0
1 1


Output

3 4


Input

6
-1 0
0 -1
1 0
1 1
-4 -5
-4 -6


Output

6 5

Solution (in JAVA):

Solution:
import java.util.*;
import java.io.*;
import java.io.FileWriter; 
import java.math.BigInteger;

// Solution

public class Main 
{    
  public static void main (String[] argv) 
  {
	  new Main();
  } 
     
  
  boolean test = false;  
  final int[][] dirs8 = {{0,1}, {0,-1}, {-1,0}, {1,0}, {1,1},{1,-1},{-1,1},{-1,-1}};
  final int MOD = 998244353;//1000000007;  
  int n_bit = 1;
  int[] bit;
  
  class Ray implements Comparable<Ray> {
      int x, y;
      int id;
      public Ray(int x, int y, int id)
      {
          this.x = x;
          this.y = y;
          this.id = id;
      }
      
      @Override 
      public int compareTo(Ray o)
      {
          if (x == 0){
              if (y > 0) {
                  if (o.x > 0 && o.y >= 0)
                      return 1;
                  return -1;
              }else {
                  if (o.x > 0 && o.y < 0)
                      return -1;
                  return 1;                  
              }
          }
          
          if (x > 0 && y == 0) return -1;
          if (x < 0 && y == 0){
              if (o.y >= 0) return 1;
              return -1;
          }
          
          if (x > 0 && y > 0){
              if (o.x > 0 && o.y >= 0 && 1L * y * o.x > 1L * x * o.y)
                return 1;
              return -1;
          }
          
          if (x < 0 && y > 0) {
              if ((o.x >= 0 && o.y >= 0) || (o.x < 0 && o.y > 0 && 1L * y * o.x > 1L * x * o.y))
                  return 1;
              return -1;
          }
          
          if (x < 0 && y < 0){
              if (o.y >= 0 || (o.x < 0 && o.y < 0 && 1L * y * o.x > 1L * x * o.y))
                  return 1;
              return -1;              
          }
          
          if (o.x > 0 && o.y < 0 && 1L * y * o.x < 1L * x * o.y)
              return -1;
          return 1;          
      }
      
      
  }
  public Main()   {
	FastReader in = new FastReader(new BufferedReader(new InputStreamReader(System.in)));
	
     
    //FastReader in = new FastReader(new BufferedReader(new FileReader("Main.in")));   
    
    //int nt = in.nextInt();    
    int nt = 1;
    StringBuilder sb = new StringBuilder();
    
    
    for (int it = 0; it < nt; it++) 
    {
        
       int n = in.nextInt();
       Ray[] points = new Ray[n];
       for (int i = 0; i < n; i++){
           int x = in.nextInt();
           int y = in.nextInt();
           points[i] = new Ray(x, y, i+1);
       }
       
       Arrays.sort(points);
       
       //for (int i = 0; i < n; i++)
        //   System.out.println("point " + i + " : " + points[i].id);
       
       int minp = 0;
       long[] minDiff = getAngle(points[0], points[1]);
       
       for (int i = 1; i < n; i++){
           long[] diff = getAngle(points[(i+1) % n], points[i]);
           
       //    System.out.println("angle for " + points[i].id + " to " + points[(i+1) % n].id + " = " + diff[0] + "/" + diff[1]);
           if (smaller(diff, minDiff)){
               minDiff = diff;
               minp = i;
           }           
       }
       
       
       
       System.out.println(points[minp].id + " " + points[(minp+1)%n].id);
       
       //System.out.println();
       //String ans = new String(a);
       //sb.append(ans);
    }
    //System.out.print(sb);
  }
  
  private long[] getAngle(Ray v1, Ray v2)
  {
      long num = 1L * v1.x * v2.x + 1L * v1.y * v2.y;
      long sign = 1;
      if (num < 0) sign = -1;
      
      num *= num;
      long dem = d2(v1.x, v1.y) * d2(v2.x, v2.y);
      long[] ans = new long[2];
      ans[0] = num * sign;
      ans[1] = dem;
      return ans;
  }
  
  private long d2(int x, int y){
      return 1L * x * x + 1L * y * y;
  }
  
  private boolean smaller(long[] ang1, long[] ang2)
  {
      BigInteger num1 = new BigInteger(String.valueOf(abs(ang1[0])));
      BigInteger dem1 = new BigInteger(String.valueOf(abs(ang1[1])));
      BigInteger num2 = new BigInteger(String.valueOf(abs(ang2[0])));
      BigInteger dem2 = new BigInteger(String.valueOf(abs(ang2[1])));

      
      if (ang1[0] >= 0) 
      {
        if(ang2[0] >= 0)      
            return num1.multiply(dem2).compareTo(dem1.multiply(num2)) > 0;
        return true;
      }else {
          if (ang2[0]>= 0) return false;
          
          return num1.multiply(dem2).compareTo(dem1.multiply(num2)) < 0;
          
      }
  }
  
  private int[] build_z_function(String s)
  {
      int n = s.length();
      int[] zfun = new int[n];
      
      int l = -1, r = -1;
      for (int i = 1; i < n; i++)
      {
         // Set the start value
         if (i <= r)
            zfun[i] = Math.min(zfun[i-l], r - i + 1);
         
         while (i + zfun[i] < n && s.charAt(i + zfun[i]) == s.charAt(zfun[i])) 
             zfun[i]++;             
         
         if (i + zfun[i] - 1> r){
             l = i;
             r = i + zfun[i] - 1;
         }
      }
      
      if (test)
      {
          System.out.println("Z-function of " + s);
          for (int i = 0; i < n; i++) System.out.print(zfun[i] + " ");
          System.out.println();
      }
      return zfun;
  }
  
  private int query(int p)
  {
      int sum = 0;
      for (; p > 0; p -= (p & (-p)))
      {
          sum += bit[p];
      }
      return sum;
  }
  
  private void add(int p, int val)
  {
      //System.out.println("add to BIT " + p);
      for (; p <= n_bit; p += (p & (-p)))
      {
          bit[p] += val;
      }
  }
  
  
  
  private List<Integer> getMinFactor(int sum)
  {
      List<Integer>  factors = new ArrayList<>();
      
               for (int sz = 2; sz <= sum / sz; sz++){
                   if (sum % sz == 0) {
                       factors.add(sz);
                       factors.add(sum / sz);
                   }
               }
               if (factors.size() == 0)
                   factors.add(sum);
          
      return factors;
  }
  
  /* Tree class */
  class Tree {
      int V = 0;
      int root = 0;
      List<Integer>[] nbs;
      int[][] timeRange;
      int[] subTreeSize;
      int t;
      boolean dump = false;
      
      public Tree(int V, int root)
      {
          if (dump) 
              System.out.println("build tree with size = " + V + ", root = " + root); 
          
          this.V = V;          
          this.root = root;
          nbs = new List[V];
          subTreeSize = new int[V];
          for (int i = 0; i < V; i++)
              nbs[i] = new ArrayList<>();
          
              
      }
      
      public void doneInput()
      {
          dfsEuler();
      }
      
      public void addEdge(int p, int q)
      {
          nbs[p].add(q);
          nbs[q].add(p);
      }
      
      private void dfsEuler()
      {
          timeRange = new int[V][2];          
          t = 1;
          dfs(root);           
      }
      
      private void dfs(int node)
      {
          if (dump)
              System.out.println("dfs on node " + node + ", at time " + t);
          timeRange[node][0] = t;
          
          for (int next : nbs[node]) {
              if (timeRange[next][0] == 0)
              {
                  ++t;
                  dfs(next);                  
              }
          }
          timeRange[node][1] = t;
          subTreeSize[node] = t - timeRange[node][0] + 1;
      }
      
      public List<Integer> getNeighbors(int p) {
          return nbs[p];
      }
      
      public int[] getSubTreeSize(){
          return subTreeSize;
      }
      
      public int[][] getTimeRange()
      {
          if (dump){
              for (int i = 0; i < V; i++){
                  System.out.println(i + ": " + timeRange[i][0] + " - " + timeRange[i][1]);
              }
          }
          return timeRange;
      }
      
  }
  
  /* segment tree */
  class SegTree {
      int[] a;
      int[] tree;
      int n;
      boolean dump = false;
      
      public SegTree(int n)
      {
          if (dump)
              System.out.println("create segTree with size " + n);
          this.n = n;
          tree = new int[n*4];
          
      }
      
      public SegTree(int n, int[] a) {
          this(n);
          this.a = a;
          buildTree(1, 0, n-1);          
      }
      
      private void buildTree(int node, int lo, int hi)
      {
          if (lo == hi) {
              tree[node] = lo;
              return;
          }
          
          int m = (lo + hi) / 2;
          buildTree(node * 2, lo, m);
          buildTree(node * 2 + 1, m + 1, hi);
          pushUp(node, lo, hi);
      }
      
      
      private void pushUp(int node, int lo, int hi)
      {
          if (lo >= hi) return;
          int lid = tree[node * 2];
          int rid = tree[node * 2 + 1];
          
          int tid = a[lid] >= a[rid] ? lid : rid;
          tree[node] = tid;
          // add combine fcn
      }
      
      
      
      
      
      public void update(int node, int lo, int hi, int p, int val){
          if (lo == hi)
          {
              a[lo] = val;
              return;
          }
          
          int m = (lo + hi) / 2;
          if (p <= m) 
              update(node * 2, lo, m, p,val);
          else
              update(node * 2 + 1, m + 1, hi, p, val);
          pushUp(node, lo, hi);   
      }
      
      
      public int query(int node, int lo, int hi, int fr, int to)
      {
          if (fr == lo && to == hi)
              return tree[node];
          
          int m = (lo + hi) / 2;
          if (to <= m) 
              return  query(node * 2, lo, m, fr, to);
          else if (fr > m)
              return query(node * 2 + 1, m + 1, hi, fr, to);
          
          int lid = query(node * 2, lo, m, fr, m);
          int rid = query(node * 2 + 1, m + 1, hi, m + 1, to);
          return a[lid] >= a[rid] ? lid : rid;
      }
      
      
  }
  
  
  private long inv(long v)
  {
      return pow(v, MOD-2);
  }
  
  private long pow(long v, int p)
  {
      long ans = 1;
      while (p > 0)
      {
          if (p % 2 == 1)
              ans = ans * v % MOD;
          v = v * v % MOD;
          p = p / 2;
      }
      return ans;
  }
  
  private double dist(double x, double y, double xx, double yy)
  {
      return Math.sqrt((xx - x) * (xx - x) + (yy - y) * (yy - y));
  }
  

  
 
  private int mod_add(int a, int b) {
      int v = a + b;
      if (v >= MOD) v -= MOD;
      return v;
  }
  
  
  private long overlap(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
      if (x1 > x3) return overlap(x3, y3, x4, y4, x1, y1, x2, y2);
      
      if (x3 > x2 || y4 < y1 || y3 > y2) return 0L;
      
      //(x3, ?, x2, ?)
      int yL = Math.max(y1, y3);
      int yH = Math.min(y2, y4); 
      int xH = Math.min(x2, x4);
      
      return f(x3, yL, xH, yH);
  }
  //return #black cells in rectangle
  private long f(int x1, int y1, int x2, int y2) {
      long dx = 1L + x2 - x1;
      long dy = 1L + y2 - y1;
      if (dx % 2 == 0 || dy % 2 == 0 || (x1 + y1) % 2 == 0) 
          return 1L * dx * dy / 2;
      return 1L * dx * dy / 2 + 1;
  }
  
  private int distM(int x, int y, int xx, int yy) {
      return abs(x - xx) + abs(y - yy);
  }
  
  private boolean less(int x, int y, int xx, int yy) {
      return x < xx || y > yy;
  }
  
  private int mul(int x, int y) {
      return (int)(1L * x * y % MOD);
  }
  
  
 
  
  private int nBit1(int v) {
      int v0 = v;
      int c = 0;
      while (v != 0) {
          ++c;
          v = v & (v - 1);
      }
      return c;
  }
  
  private long abs(long v) {
      return v > 0 ? v : -v;
  }
  
  private int abs(int v) {
      return v > 0 ? v : -v;
  }
  
  private int common(int v) {
      int c = 0;
      while (v != 1) {
          v = (v >>> 1);
          ++c;
      }
      
      return c;
  }
  
  private void reverse(char[] a, int i, int j) {
      while (i < j) {
          swap(a, i++, j--);
      }
  }
  
  private void swap(char[] a, int i, int j) {
      char t = a[i];
      a[i] = a[j];
      a[j] = t;
  }
  
  private int gcd(int x, int y) {
      if (y == 0) return x;
      return gcd(y, x % y);
  }
  private long gcd(long x, long y) {
      if (y == 0) return x;
      return gcd(y, x % y);
  }
  private int max(int a, int b) {
      return a >  b ? a : b;
  }
  
  private long max(long a, long b) {
      return a >  b ? a : b;
  }
  
  private int min(int a, int b) {
      return a >  b ? b : a;
  }
  
  private long min(long a, long b) {
      return a >  b ? b : a;
  }
  
  static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;
 
        public FastReader(BufferedReader in)
        {            
            br = in;
        }
 
        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    String line = br.readLine();
                    if (line == null || line.length() == 0) return "";
                    st = new StringTokenizer(line);
                }
                catch (IOException  e)
                {
                    return "";
                    //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)
            {
                return null;
                //e.printStackTrace();
            }
            return str;
        }
    }
}