#include using i64 = long long; using u64 = unsigned long long; using u32 = unsigned; using u128 = unsigned __int128; using i128 = __int128; struct point2d { public: int x, y; point2d() : x(0), y(0) {}; point2d(int x_, int y_) : x(x_), y(y_) {}; point2d operator-() const { return point2d(-x, -y); } int quadrant() const { if (y == 0) return x > 0 ? 0 : 4; if (x == 0) return y > 0 ? 2 : 6; if (y > 0) return x > 0 ? 1 : 3; return x > 0 ? 7 : 5; } bool operator==(const point2d& p) const { return x == p.x && y == p.y; } bool operator!=(const point2d& p) const { return x != p.x || y != p.y; } bool operator<(const point2d& p) const { int qa = quadrant(), qb = p.quadrant(); if (qa != qb) return qa < qb; return 1LL * x * p.y > 1LL * y * p.x; } }; void solve() { int N; std::cin >> N; std::vector P(N); std::vector pd; for(int i = 0; i < N; i ++) { std::cin >> P[i].x >> P[i].y; int g = std::gcd(std::abs(P[i].x), std::abs(P[i].y)); P[i].x /= g; P[i].y /= g; pd.push_back(P[i]); pd.push_back(- P[i]); } std::sort(pd.begin(), pd.end()); pd.erase(std::unique(pd.begin(), pd.end()), pd.end()); int M = (int)pd.size() / 2; std::vector seq(2 * M); for(int i = 0; i < N; i ++) { int ptr = std::lower_bound(pd.begin(), pd.end(), P[i]) - pd.begin(); seq[ptr] ++; } int sump = 0, sumq = 0; for(int i = 0; i < M; i ++) sump += seq[i]; sumq = sump + seq[M]; i64 ans = 0; for(int i = 0; i < 2 * M; i ++) { ans += 1LL * sumq * (sumq - 1) * (sumq - 2) - 1LL * sump * (sump - 1) * (sump - 2); sump += seq[i < M ? i + M : i - M] - seq[i]; sumq += seq[i < M - 1 ? i + M + 1 : i - M + 1] - seq[i]; } for(int i = 0; i < M; i ++) ans -= seq[i] * seq[i + M] * (seq[i] + seq[i + M] - 2) * 3; std::cout << (1LL * N * (N - 1) * (N - 2) - ans) / 6; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T = 1; //std::cin >> T; while (T--) { solve(); } return 0; }