Problem:
Score: 500 points

Problem Statement

We have caught N sardines. The deliciousness and fragrantness of the i-th sardine is A_i and B_i, respectively.

We will choose one or more of these sardines and put them into a cooler. However, two sardines on bad terms cannot be chosen at the same time.

The i-th and j-th sardines (i \neq j) are on bad terms if and only if A_i \cdot A_j + B_i \cdot B_j = 0.

In how many ways can we choose the set of sardines to put into the cooler? Since the count can be enormous, print it modulo 1000000007.

Constraints

All values in input are integers.

1 \leq N \leq 2 \times 10^5

-10^{18} \leq A_i, B_i \leq 10^{18}

Input

Input is given from Standard Input in the following format:

N
A_1 B_1
:
A_N B_N

Output

Print the count modulo 1000000007.

Sample Input 1

3
1 2
-1 1
2 -1

Sample Output 1

5

There are five ways to choose the set of sardines, as follows:

The 1-st

The 1-st and 2-nd

The 2-nd

The 2-nd and 3-rd

The 3-rd

Sample Input 2

10
3 2
3 2
-1 1
2 -1
-3 -9
-8 12
7 7
8 1
8 2
8 4

Sample Output 2

479

Solution in Fortran (GNU Fortran 9.2.1) (judge verdict: Wrong Answer)

module module_modint
  use, intrinsic :: iso_fortran_env
  implicit none
  integer(int64) :: modu = 1000000007_8
  type modint
    integer(int64), private :: val = 0_8
  contains
    procedure, private :: asgn => asgn
    procedure, private :: add => add
    procedure, private :: sub => sub
    procedure, private :: mul => mul
    procedure, private :: div => div
    procedure, private :: pow => pow
    procedure, public :: inv => inv
    procedure, public :: get => get
    generic, public :: assignment(=) => asgn
    generic, public :: operator(+) => add
    generic, public :: operator(-) => sub
    generic, public :: operator(*) => mul
    generic, public :: operator(/) => div
    generic, public :: operator(**) => pow
  end type
  interface modint
    module procedure :: new_modint, new_modint_with_num
  end interface modint
  interface operator(+)
    module procedure :: add_r
  end interface
  interface operator(-)
    module procedure :: sub_r
  end interface
  interface operator(*)
    module procedure :: mul_r
  end interface
  interface operator(/)
    module procedure :: div_r
  end interface
  interface dot_product
    module procedure :: dot_prod
  end interface dot_product
  interface matmul
    module procedure :: matmul1, matmul2, matmul3
  end interface matmul
contains
  pure elemental integer(int64) function to_int64(num) result(ret)
    class(*), intent(in) :: num
    select type (num)
    type is (integer(int64))
      ret = num
    type is (integer(int32))
      ret = int(num, int64)
    type is (integer(int16))
      ret = int(num, int64)
    type is (integer(int8))
      ret = int(num, int64)
    class default
      ret = 0_8
      ret = 1_8/ret
    end select
  end
  pure elemental type(modint) function new_modint()
  end
  pure elemental type(modint) function new_modint_with_num(num) result(ret)
    class(*), intent(in) :: num
    ret%val = to_int64(num)
  end
  pure elemental subroutine asgn(this,other)
    class(modint), intent(inout) :: this
    class(*), intent(in) :: other
    integer(int64) :: val
    select type (other)
    type is (modint)
      this%val = other%val
    class default
      val = to_int64(other)
      if (0_8 <= val .and. val < modu) then
        this%val = val
      else
        this%val = modulo(val,modu)
      end if
    end select
  end
  pure elemental type(modint) function add(this,other) result(ret)
    class(modint), intent(in) :: this
    class(*), intent(in) :: other
    integer(int64) :: val
    select type (other)
    type is (modint)
      if (0_8 <= this%val+other%val .and. this%val+other%val < modu) then
        ret%val = this%val+other%val
      else
        ret%val = this%val+other%val-modu
      end if
    class default
      val = to_int64(other)
      if (0_8 <= this%val+val .and. this%val+val < modu) then
        ret%val = this%val+val
      else
        ret%val = modulo(this%val+val,modu)
      end if
    end select
  end
  pure elemental type(modint) function sub(this,other) result(ret)
    class(modint), intent(in) :: this
    class(*), intent(in) :: other
    integer(int64) :: val
    select type (other)
    type is (modint)
      if (0_8 <= this%val-other%val .and. this%val-other%val < modu) then
        ret%val = this%val-other%val
      else
        ret%val = this%val-other%val+modu
      end if
    class default
      val = to_int64(other)
      if (0_8 <= this%val-val .and. this%val-val < modu) then
        ret%val = this%val-val
      else
        ret%val = modulo(this%val-val,modu)
      end if
    end select
  end
  pure elemental type(modint) function mul(this,other) result(ret)
    class(modint), intent(in) :: this
    class(*), intent(in) :: other
    integer(int64) :: val
    select type (other)
    type is (modint)
      val = other%val
    class default
      val = to_int64(other)
    end select
    if (0_8 <= this%val*val .and. this%val*val < modu) then
      ret%val = this%val*val
    else
      ret%val = modulo(this%val*val,modu)
    end if
  end
  pure elemental type(modint) function div(this,other) result(ret)
    class(modint), intent(in) :: this
    class(*), intent(in) :: other
    type(modint) :: tmp
    call asgn(tmp,other)
    call asgn(ret,mul(this,inv(tmp)))
  end
  pure elemental integer(int64) function get(this)
    class(modint), intent(in) :: this
    get = this%val
  end
  pure elemental type(modint) function inv(this)
    class(modint), intent(in) :: this
    integer(int64) :: a, b, c, n
    integer(int64) :: x, y, z, m
    a = this%val
    b = modu
    c = 0_8
    n = 1_8
    do while (b /= 0_8)
      x = b
      y = mod(a,b)
      z = n-a/b*c
      m = c
      a = x
      b = y
      c = z
      n = m
    end do
    call asgn(inv,n)
  end
  pure elemental type(modint) function pow(this,other)
    class(modint), intent(in) :: this
    class(*), intent(in) :: other
    integer(int64) :: n
    type(modint) :: i
    pow%val = 1_8
    i%val = this%val
    n = to_int64(other)
    do while (n > 0_8)
      if (btest(n,0)) call asgn(pow,mul(pow,i))
      call asgn(i,mul(i,i))
      n = rshift(n,1)
    end do
  end
  pure elemental type(modint) function add_r(other,this) result(ret)
    class(modint), intent(in) :: this
    class(*), intent(in) :: other
    call asgn(ret,add(this,other))
  end
  pure elemental type(modint) function sub_r(other,this) result(ret)
    class(modint), intent(in) :: this
    class(*), intent(in) :: other
    call asgn(ret,sub(this,other))
  end
  pure elemental type(modint) function mul_r(other,this) result(ret)
    class(modint), intent(in) :: this
    class(*), intent(in) :: other
    call asgn(ret,mul(this,other))
  end
  pure elemental type(modint) function div_r(other,this) result(ret)
    class(modint), intent(in) :: this
    class(*), intent(in) :: other
    call asgn(ret,div(this,other))
  end
  pure type(modint) function dot_prod(x,y) result(ret)
    type(modint), intent(in) :: x(:), y(:)
    integer :: i
    if (size(x,1) /= size(y,1)) i = to_int64("")
    do i = 1, size(x,1)
      call asgn(ret,add(ret,mul(x(i),y(i))))
    end do
  end
  pure function matmul1(x,y) result(ret)
    type(modint), intent(in) :: x(:,:), y(:)
    type(modint) :: ret(size(x,1))
    integer :: i
    if (size(x,2) /= size(y,1)) i = to_int64("")
    do i = 1, size(x,1)
      call asgn(ret(i),dot_prod(x(i,:),y))
    end do
  end
  pure function matmul2(x,y) result(ret)
    type(modint), intent(in) :: x(:), y(:,:)
    type(modint) :: ret(size(y,2))
    integer :: i
    if (size(x,1) /= size(y,1)) i = to_int64("")
    do i = 1, size(y,2)
      call asgn(ret(i),dot_prod(x,y(:,i)))
    end do
  end
  pure function matmul3(x,y) result(ret)
    type(modint), intent(in) :: x(:,:), y(:,:)
    type(modint) :: ret(size(x,1),size(y,2))
    integer :: i
    if (size(x,2) /= size(y,1)) i = to_int64("")
    do i = 1, size(x,1)
      call asgn(ret(i,:),matmul2(x(i,:),y))
    end do
  end
end module module_modint
module modulo_utils
  use module_modint
  implicit none
  type(modint), allocatable :: f(:), invf(:)
contains
  subroutine init(n)
    integer, intent(in) :: n
    integer :: i
    if (allocated(f)) deallocate(f)
    if (allocated(invf)) deallocate(invf)
    allocate(f(0:n),invf(0:n))
    f(0) = 1
    do i = 1, n
      f(i) = f(i-1)*i
    end do
    invf(n) = f(n)%inv()
    do i = n, 1, -1
      invf(i-1) = invf(i)*i
    end do
  end
  pure elemental type(modint) function perm(n,k)
    integer, intent(in) :: n, k
    if (k > n .or. n < 0 .or. k < 0) return
    perm = f(n)*invf(n-k)
  end
  pure elemental type(modint) function comb(n,k)
    integer, intent(in) :: n, k
    comb = perm(n,k)*invf(k)
  end
  pure elemental type(modint) function homo(n,k)
    integer, intent(in) :: n, k
    homo = 1
    if (n == 0 .and. k == 0) return
    homo = comb(n+k-1,k)
  end
end module modulo_utils
program bullet
  use module_modint
  use modulo_utils
  implicit none
  real(16), parameter :: pi = 3.14159265358979323846264338327950288_16
  real(16), parameter :: hi = 0.5_16*pi
  integer :: n, i, k1, k2, k3, k4
  integer(8) :: c(200000,2) = 0_8
  real(16) :: t(-200000:400000) = 0.0_16
  type(modint) :: ans
  read(*,*) n
  do i = 1, n
    read(*,*) c(i,:)
  end do
  call merge_sort(c(1:n,:))
  do i = 1, n
    t(i) = atan2(real(c(i,2),16),real(c(i,1),16))
  end do
  t(-n+1:0) = t(1:n)-2.0_16*pi
  t(n+1:2*n) = t(1:n)+2.0_16*pi
  do i = 1, n
    k1 = right_lower_bound(i)
    k2 = right_upper_bound(i)
    k3 = left_lower_bound(i)
    k4 = left_upper_bound(i)
    ans = ans + modint(2)**(n-k2+k1-k3+k4-1)
  end do
  write(*,'(i0)') ans%get()
contains
  function right_lower_bound(i) result(l)
    integer, intent(in) :: i
    integer :: l, r, m
    l = i
    r = 2*n+1
    do while (r-l > 1)
      m = (l+r)/2
      if (t(m)-t(i) < hi) then
        l = m
      else
        r = m
      end if
    end do
  end
  function right_upper_bound(i) result(r)
    integer, intent(in) :: i
    integer :: l, r, m
    l = i
    r = 2*n
    do while (r-l > 1)
      m = (l+r)/2
      if (t(m)-t(i) <= hi) then
        l = m
      else
        r = m
      end if
    end do
  end
  function left_upper_bound(i) result(l)
    integer, intent(in) :: i
    integer :: l, r, m
    l = -n+1
    r = i
    do while (r-l > 1)
      m = (l+r)/2
      if (t(i)-t(m) < hi) then
        l = m
      else
        r = m
      end if
    end do
  end
  function left_lower_bound(i) result(r)
    integer, intent(in) :: i
    integer :: l, r, m
    l = -n
    r = i
    do while (r-l > 1)
      m = (l+r)/2
      if (t(i)-t(m) <= hi) then
        l = m
      else
        r = m
      end if
    end do
  end
  subroutine merge_sort(a)
    integer(8), intent(inout) :: a(:,:)
    integer :: n, m, l, i, u
    n = size(a,1)
    m = n
    l = 1
    do while (m > 1)
      do i = 1, m/2
        u = min(2*i*l,n)
        call merger(a(2*(i-1)*l+1:(2*i-1)*l,:),a((2*i-1)*l+1:u,:))
      end do
      l = 2*l
      m = (m+1)/2
    end do
  end
  subroutine merger(a1,a2)
    integer(8), intent(inout) :: a1(:,:), a2(:,:)
    integer(8) :: a(size(a1,1)+size(a2,1),size(a1,2))
    integer :: i1, i2, n1, n2
    real(16) :: t1, t2
    i1 = 1
    i2 = 1
    n1 = size(a1,1)
    n2 = size(a2,1)
    do while (i1 <= n1 .and. i2 <= n2)
      t1 = atan2(real(a1(i1,2),16),real(a1(i1,1),16))
      t2 = atan2(real(a2(i2,2),16),real(a2(i2,1),16))
      if (t1 <= t2) then
        a(i1+i2-1,:) = a1(i1,:)
        i1 = i1+1
      else
        a(i1+i2-1,:) = a2(i2,:)
        i2 = i2+1
       end if
    end do
    if (i1 <= n1) then
      a(i1+i2-1:n1+n2,:) = a1(i1:n1,:)
    else
      a(i1+i2-1:n1+n2,:) = a2(i2:n2,:)
    end if
    a1 = a(1:n1,:)
    a2 = a(n1+1:n1+n2,:)
  end
end program bullet