#![allow(unused_imports)]
#![allow(clippy::many_single_char_names)]
#![allow(clippy::suspicious_arithmetic_impl)]

// using Rust(1.42.0)
// My Library Repo is at "https://github.com/Loptall/prcn_lib"
// check available crates on AtCoder at "https://atcoder.jp/contests/language-test-202001"

/*
    AtCoder Language Update 2020204 お疲れ様でした! 有難いです(p.s. 過去問対応もありがとうございます)
*/

// from std...
use std::cmp::{
    max, min,
    Ordering::{Equal, Greater, Less},
};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
use std::mem::swap;
use std::ops::*;
use std::usize::{MAX, MIN};
use std::{i128, i16, i32, i64, i8, isize, u128, u16, u32, u64, u8, usize};

// Dep crates are...
use itertools::*;
use itertools_num::*;
use lazy_static::lazy_static;
use maplit::{btreemap, btreeset, hashmap, hashset};
use num_bigint::{BigInt, BigUint};
use num_integer::{binomial, gcd, lcm, Integer};
use permutohedron::Heap;
use petgraph::unionfind::UnionFind;
use proconio::{fastout, input, is_stdin_empty, marker::*};
use rand::random;

use num::rational::Rational;
use num::traits::{One, Zero};

// code...
// #[fastout]
fn main() {
    input! {
        n: usize,
        ab: [(isize, isize); n]
    }

    let mut slant = HashMap::new();

    for (a, b) in ab {
        let h = slant.entry(Rational::new(a, b)).or_insert(0);
        *h += 1usize;
    }

    let mut vans = 0;
    for k in slant.keys().filter(|x| **x >= Rational::zero()) {
        let posi = slant[k];
        let neg = *slant.get(&-(Rational::one() / k)).unwrap_or(&0);
        dbg!(posi, neg);
        vans += (2usize.pow(posi as u32) - 1)
            * (2usize.pow(neg as u32) - 1)
            * 2usize.pow((n - posi - neg) as u32);
    }

    println!("{}", 2usize.pow(n as u32) - vans - 1);
}
