Language: C++

#include <bits/stdc++.h>
using namespace std;

#define rep(i,x,y) for(ll i=(x);i<(y);i++)
#define rrep(i,x,y) for(ll i=(ll)(y)-1;i>=(x);i--)
#define all(x) (x).begin(),(x).end()
#ifdef LOCAL
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl
#define itrdebug(x) cerr << #x << " "; for (auto & el : (x)) {cerr << (el) << " ";} cerr << endl
#define dassert(...) assert(__VA_ARGS__)
#else
#define debug(x)
#define itrdebug(x)
#define dassert(...)
#endif
//#define int long long

typedef long long ll;
const ll MOD = 1e9 + 7;
const long double EPS = 1e-8;

long long getGcd(long long a, long long b) {
    if (a < b) swap(a, b);
    long long r = a % b;
    while(r!=0){
        a = b;
        b = r;
        r = a % b;
    }
    return b;
}

namespace mod {
    long long pow(long long a, long long x, long long p) {
        long long res = 1;
        while(x > 0) {
            if( x % 2 != 0) {
                res = (res * a) % p;
            }
            a = (a * a) % p;
            x /= 2;
        }
        return res;
    }

    long long inverse(long long a, long long p) {
        //calculates the modular multiplicative of a mod m.
        //(assuming p is prime).
        return pow(a, p-2, p);
    }

    long long factorial(long long a, long long p) {
        long long fact = 1;
        for (long long i=2; i<=a; i++) {
            fact *= i;
            fact %= p;
        }
        return fact;
    }

    long long MOD = 1e9+7;

    template <long long MOD>
    struct mint {
        long long x;
        mint(long long x = 0) : x((x%MOD+MOD)%MOD){}
        mint operator-() const { return mint<MOD>(-x);}
        mint& operator+=(const mint<MOD> a) {
            if ((x += a.x) >= MOD) x -= MOD;
            return *this;
        }
        mint& operator-=(const mint<MOD> a) {
            if ((x += MOD-a.x) >= MOD) x -= MOD;
            return *this;
        }
        mint& operator*=(const mint<MOD> a) {
            (x *= a.x) %= MOD; return *this;
        }
        mint operator+(const mint<MOD> a) const { return mint<MOD>(*this) += a;}
        mint operator-(const mint<MOD> a) const { return mint<MOD>(*this) -= a;}
        mint operator*(const mint<MOD> a) const { return mint<MOD>(*this) *= a;}
        mint pow(long long t) const {
            if (!t) return 1;
            mint<MOD> a = pow(t>>1);
            a *= a;
            if (t&1) a *= *this;
            return a;
        }

        // for prime mod
        mint inv() const { return pow(MOD-2);}
        mint& operator/=(const mint<MOD> a) { return *this *= a.inv();}
        mint operator/(const mint<MOD> a) const { return mint<MOD>(*this) /= a;}
    };
}
std::istream& operator>>(std::istream& is, const mod::mint<MOD>& a) { return is >> a.x;}
std::ostream& operator<<(std::ostream& os, const mod::mint<MOD>& a) { return os << a.x;}

struct hash_pair {
    template<class T1, class T2>
    size_t operator()(const pair<T1, T2> &p) const {
        auto hash1 = hash<T1>{}(p.first);
        auto hash2 = hash<T2>{}(p.second);

        size_t seed = 0;
        seed ^= hash1 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        seed ^= hash2 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        seed ^= m_hash_pair_random + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        return seed;
    }
};

void solve(long long N, std::vector<long long> A, std::vector<long long> B){
    ll abZeroCnt = 0;
    unordered_map<pair<ll, ll>, ll, hash_pair> cnt;
    rep(i,0,N) {
        if (A[i] == 0 && B[i] == 0) {
            abZeroCnt++;
        } else if (A[i] == 0) {
            cnt[{1, 0}]++;
        } else if (B[i] == 0) {
            cnt[{-1, 0}]++;
        } else {
            ll a = A[i], b = B[i];
            ll gcd = getGcd(abs(a), abs(b));
            a /= gcd; b /= gcd;
            if (b < 0) {
                a *= -1;
                b *= -1;
            }
            cnt[{a, b}]++;
        }
    }
    mod::mint<MOD> answer = 1;
    for (const auto & el : cnt) {
        ll a = el.first.first, b = el.first.second;
        mod::mint<MOD> current = mod::pow(2, el.second, MOD);
        auto counterpart = a > 0 ? pair<ll, ll>{-b, a} : pair<ll, ll>{b, -a};
        if (cnt.find(counterpart) != cnt.end()) {
            current += mod::pow(2, cnt[counterpart], MOD) - 1;
            cnt.erase(counterpart);
        }
        answer *= current;
    }
    answer += abZeroCnt - 1;
    cout << answer << endl;
}

signed main(){
    // ios_base::sync_with_stdio(false);
    // cin.tie(NULL);
    long long N;
    scanf("%lld",&N);
    std::vector<long long> A(N);
    std::vector<long long> B(N);
    for(int i = 0 ; i < N ; i++){
        scanf("%lld",&A[i]);
        scanf("%lld",&B[i]);
    }
    solve(N, std::move(A), std::move(B));
    return 0;
}


Compiler output:
a.cc: In member function 'size_t hash_pair::operator()(const std::pair<_T1, _T2>&) const':
a.cc:108:17: error: 'm_hash_pair_random' was not declared in this scope
  108 |         seed ^= m_hash_pair_random + 0x9e3779b9 + (seed << 6) + (seed >> 2);
      |                 ^~~~~~~~~~~~~~~~~~