#include<bits/stdc++.h>
using namespace std;
long long A[200009];
long long x[200009];
long long y[200009];
struct line
{
  long long slopea,slopeb;
  long long ya,yb;
};
bool cmp(const line &a,const line &b)
{
  if(a.slopea * b.slopeb != a.slopeb * b.slopea)
  {
    return a.slopea * b.slopeb < a.slopeb * b.slopea;
  }
  return a.ya * b.yb < a.yb * b.ya;
}
bool cmp1(const line &a,const line &b)
{
  return a.ya < b.ya;
}
bool cmp2(const line &a,const line &b)
{
  return a.ya < b.ya;
}
bool same(line a,line b)
{
  return(a.slopea == b.slopea && a.slopeb == b.slopeb && a.ya == b.ya && a.yb == b.yb);
}
bool same1(line a,line b)
{
  return(a.slopea == b.slopea && a.slopeb == b.slopeb);
}
int main()
{
  long long M,i,j,k,N,now,ans,before;
  vector<line> temp;
  vector<line> hor;
  vector<line> ver;
  vector<line> temps;
  vector<line> hors;
  vector<line> vers;
  line t;
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cin >> N;
  for(i = 0;i < N;i++)
  {
    cin >> x[i] >> y[i];
  }
  for(i = 0;i < N;i++)
  {
    for(j = i+1;j < N;j++)
    {
      if(x[i] == x[j])
      {
        t.slopea = -1;
        t.slopeb = 0;
        t.ya = x[i];
        t.yb = 1;
        ver.push_back(t);
      }
      else if(y[i] == y[j])
      {
        t.slopea = 0;
        t.slopeb = 1;
        t.ya = y[i];
        t.yb = 1;
        hor.push_back(t);
      }
      else
      {
        t.slopea = y[j] - y[i];
        t.slopeb = t.yb = x[j] - x[i];
        t.ya = x[j]*y[i] - x[i]*y[j];
        k = __gcd(abs(t.slopea),abs(t.slopeb));
        t.slopea /= k;
        t.slopeb /= k;
        if(t.slopeb < 0)
        {
          t.slopea *= -1;
          t.slopeb *= -1;
        }
        k = __gcd(abs(t.ya),abs(t.yb));
        t.ya /= k;
        t.yb /= k;
        if(t.yb < 0)
        {
          t.ya *= -1;
          t.yb *= -1;
        }
        temp.push_back(t);
      }
    }
  }
  sort(temp.begin(),temp.end(),cmp);
  sort(ver.begin(),ver.end(),cmp1);
  sort(hor.begin(),hor.end(),cmp2);
  //system("pause");
  for(i = 0;i < temp.size();i++)
  {
    i++;
    while(i < temp.size() && same(temp[i],temp[i-1]))
      i++;
    temps.push_back(temp[i-1]);
    i--;
  }
  for(i = 0;i < ver.size();i++)
  {
    i++;
    while(i < ver.size() && same(ver[i],ver[i-1]))
      i++;
    vers.push_back(ver[i-1]);
    i--;
  }
  for(i = 0;i < hor.size();i++)
  {
    i++;
    while(i < hor.size() && (same(hor[i],hor[i-1])))
      i++;
    hors.push_back(hor[i-1]);
    i--;
  }
  //cout  << temp.size() << " " << hor.size() << " " << ver.size() <<endl;
  //cout  << temps.size() << " " << hors.size() << " " << vers.size() <<endl;
  ans = ((long long)temps.size()) * ((long long)hors.size()) + ((long long)temps.size()*(long long)vers.size()) +((long long)vers.size())*((long long)hors.size());
  before = 0;
  for(i = 0;i < temps.size();i++)
  {
    now = 1;
    i++;
    while(i < temps.size() && same1(temps[i],temps[i-1]))
    {
      //cout << "hhh" <<endl;
      i++;
      now++;
    }
    ans += now*before;
    //cout << i << " " << now << " " << before <<endl;
    i--;
    before += now;
  }
  cout << ans <<endl;
}


#include<bits/stdc++.h>
using namespace std;
long long A[200009];
long long x[200009];
long long y[200009];
struct line
{
  long long slopea,slopeb;
  long long ya,yb;
};
bool cmp(const line &a,const line &b)
{
  if(a.slopea * b.slopeb != a.slopeb * b.slopea)
  {
    return a.slopea * b.slopeb < a.slopeb * b.slopea;
  }
  return a.ya * b.yb < a.yb * b.ya;
}
bool cmp1(const line &a,const line &b)
{
  return a.ya < b.ya;
}
bool cmp2(const line &a,const line &b)
{
  return a.ya < b.yb;
}
bool same(line a,line b)
{
  return(a.slopea == b.slopea && a.slopeb == b.slopeb && a.ya == b.ya && a.yb == b.yb);
}
bool same1(line a,line b)
{
  return(a.slopea == b.slopea && a.slopeb == b.slopeb);
}
int main()
{
  long long M,i,j,k,N,now,ans,before;
  vector<line> temp;
  vector<line> hor;
  vector<line> ver;
  vector<line> temps;
  vector<line> hors;
  vector<line> vers;
  line t;
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cin >> N;
  for(i = 0;i < N;i++)
  {
    cin >> x[i] >> y[i];
  }
  for(i = 0;i < N;i++)
  {
    for(j = i+1;j < N;j++)
    {
      if(x[i] == x[j])
      {
        t.slopea = -1;
        t.slopeb = 0;
        t.ya = x[i];
        t.yb = 1;
        ver.push_back(t);
      }
      else if(y[i] == y[j])
      {
        t.slopea = 0;
        t.slopeb = 1;
        t.ya = y[i];
        t.yb = 1;
        hor.push_back(t);
      }
      else
      {
        t.slopea = y[j] - y[i];
        t.slopeb = t.yb = x[j] - x[i];
        t.ya = x[j]*y[i] - x[i]*y[j];
        k = __gcd(abs(t.slopea),abs(t.slopeb));
        t.slopea /= k;
        t.slopeb /= k;
        if(t.slopeb < 0)
        {
          t.slopea *= -1;
          t.slopeb *= -1;
        }
        k = __gcd(abs(t.ya),abs(t.yb));
        t.ya /= k;
        t.yb /= k;
        if(t.yb < 0)
        {
          t.ya *= -1;
          t.yb *= -1;
        }
        temp.push_back(t);
      }
    }
  }
  sort(temp.begin(),temp.end(),cmp);
  sort(ver.begin(),ver.end(),cmp1);
  sort(hor.begin(),hor.end(),cmp2);
  //system("pause");
  for(i = 0;i < temp.size();i++)
  {
    i++;
    while(i < temp.size() && same(temp[i],temp[i-1]))
      i++;
    temps.push_back(temp[i-1]);
    i--;
  }
  for(i = 0;i < ver.size();i++)
  {
    i++;
    while(i < ver.size() && same(ver[i],ver[i-1]))
      i++;
    vers.push_back(ver[i-1]);
    i--;
  }
  for(i = 0;i < hor.size();i++)
  {
    i++;
    while(i < hor.size() && (same(hor[i],hor[i-1])))
      i++;
    hors.push_back(hor[i-1]);
    i--;
  }
  //cout  << temp.size() << " " << hor.size() << " " << ver.size() <<endl;
  //cout  << temps.size() << " " << hors.size() << " " << vers.size() <<endl;
  ans = (long long)temps.size() * (long long)hors.size() + (long long)temps.size()*(long long)vers.size() +(long long)vers.size()*(long long)hors.size();
  before = 0;
  for(i = 0;i < temps.size();i++)
  {
    now = 1;
    i++;
    while(i < temps.size() && same1(temps[i],temps[i-1]))
    {
      //cout << "hhh" <<endl;
      now++;
    }
    ans += now*before;
    //cout << i << " " << now << " " << before <<endl;
    i--;
    before += now;
  }
  cout << ans <<endl;
}


#include<bits/stdc++.h>
using namespace std;
long long A[200009];
long long x[200009];
long long y[200009];
struct line
{
  long long slopea,slopeb;
  long long ya,yb;
};
bool cmp(const line &a,const line &b)
{
  if(a.slopea * b.slopeb != a.slopeb * b.slopea)
  {
    return a.slopea * b.slopeb < a.slopeb * b.slopea;
  }
  return a.ya * b.yb < a.yb * b.ya;
}
bool cmp1(const line &a,const line &b)
{
  return a.ya < b.ya;
}
bool cmp2(const line &a,const line &b)
{
  return a.ya < b.yb;
}
bool same(line a,line b)
{
  return(a.slopea == b.slopea && a.slopeb == b.slopeb && a.ya == b.ya && a.yb == b.yb);
}
bool same1(line a,line b)
{
  return(a.slopea == b.slopea && a.slopeb == b.slopeb);
}
int main()
{
  long long M,i,j,k,N,now,ans,before;
  vector<line> temp;
  vector<line> hor;
  vector<line> ver;
  vector<line> temps;
  vector<line> hors;
  vector<line> vers;
  line t;
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cin >> N;
  for(i = 0;i < N;i++)
  {
    cin >> x[i] >> y[i];
  }
  for(i = 0;i < N;i++)
  {
    for(j = i+1;j < N;j++)
    {
      if(x[i] == x[j])
      {
        t.slopea = -1;
        t.slopeb = 0;
        t.ya = x[i];
        t.yb = 1;
        ver.push_back(t);
      }
      else if(y[i] == y[j])
      {
        t.slopea = 0;
        t.slopeb = 1;
        t.ya = y[i];
        t.yb = 1;
        hor.push_back(t);
      }
      else
      {
        t.slopea = y[j] - y[i];
        t.slopeb = t.yb = x[j] - x[i];
        t.ya = x[j]*y[i] - x[i]*y[j];
        k = __gcd(abs(t.slopea),abs(t.slopeb));
        t.slopea /= k;
        t.slopeb /= k;
        if(t.slopeb < 0)
        {
          t.slopea *= -1;
          t.slopeb *= -1;
        }
        k = __gcd(abs(t.ya),abs(t.yb));
        t.ya /= k;
        t.yb /= k;
        if(t.yb < 0)
        {
          t.ya *= -1;
          t.yb *= -1;
        }
        temp.push_back(t);
      }
    }
  }
  sort(temp.begin(),temp.end(),cmp);
  sort(ver.begin(),ver.end(),cmp1);
  sort(hor.begin(),hor.end(),cmp2);
  //system("pause");
  for(i = 0;i < temp.size();i++)
  {
    i++;
    while(i < temp.size() && same(temp[i],temp[i-1]))
      i++;
    temps.push_back(temp[i-1]);
    i--;
  }
  for(i = 0;i < ver.size();i++)
  {
    i++;
    while(i < ver.size() && same(ver[i],ver[i-1]))
      i++;
    vers.push_back(ver[i-1]);
    i--;
  }
  for(i = 0;i < hor.size();i++)
  {
    i++;
    while(i < hor.size() && (same(hor[i],hor[i-1])))
      i++;
    hors.push_back(hor[i-1]);
    i--;
  }
  //cout  << temp.size() << " " << hor.size() << " " << ver.size() <<endl;
  //cout  << temps.size() << " " << hors.size() << " " << vers.size() <<endl;
  ans = (long long)temps.size() * (long long)hors.size() + (long long)temps.size()*(long long)vers.size() +(long long)vers.size()*(long long)hors.size();
  before = 0;
  for(i = 0;i < temps.size();i++)
  {
    now = 1;
    i++;
    while(i < temps.size() && same1(temps[i],temps[i-1]))
    {
      //cout << "hhh" <<endl;
      i++;
      now++;
    }
    ans += now*before;
    //cout << i << " " << now << " " << before <<endl;
    i--;
    before += now;
  }
  cout << ans <<endl;
}


#include <bits/stdc++.h>

using namespace std;

#define int long long

struct point
{
    int x, y;
    point(int val1, int val2)
    {
        x = val1;
        y = val2;
    }
    point()
    {
        x = 0;
        y = 0;
    }
};

void swap(point &a, point &b)
{
    swap(a.x, b.x);
    swap(a.y, b.y);
}

point operator+(point a, point b)
{
    point c(a.x + b.x, a.y + b.y);
    return c;
}

point operator-(point a, point b)
{
    point c(a.x - b.x, a.y - b.y);
    return c;
}

int operator*(point a, point b)
{
    return a.x * b.x + a.y * b.y;
}

int operator^(point a, point b)
{
    return a.x * b.y - a.y * b.x;
}

istream& operator>>(istream& stream, point &a)
{
    stream >> a.x >> a.y;
    return stream;
}

ostream& operator<<(ostream& stream, point &a)
{
    stream << a.x << " " << a.y << " ";
    return stream;
}

bool operator==(point a, point b)
{
    return a.x == b.x && a.y == b.y;
}

double angle(point a, point b, point c)
{
    return atan2((a - b)^(c - b), (a - b)*(c - b));
}

int twSpace(point a, point b, point c)
{
    return (a - b)^(c - b);
}

double dist(point a, point b)
{
    int f = a.x - b.x, s = a.y - b.y;
    return sqrt(f*f + s*s);
}

double linedist(point a, point b, point c)
{
    return (double)(abs(twSpace(a, b, c))) / dist(b, c);
}

double rayDist(point a, point b, point c)
{
    if (((c - b)*(a - b)) < 0)
    {
        return dist(a, b);
    }
    return linedist(a, b, c);
}

double segmentDist(point a, point b, point c)
{
    if (((c - b)*(a - b)) < 0)
    {
        return dist(a, b);
    }
    if (((b - c)*(a - c)) < 0)
    {
        return dist(a, c);
    }
    return linedist(a, b, c);
}

bool insideAngle(point a, point o, point b, point p)
{
    if (((b - o)^(a - o)) < 0)
    {
        swap(a, b);
    }
    if (((b - o)^(p - o)) >= 0 && ((a - o)^(p - o)) <= 0)
    {
        return true;
    }
    return false;
}

bool rayCross(point a, point b, point c, point d)
{
    if (((b - a)^(c - a)) == 0)
    {
        return (rayDist(c, a, b) == 0) || (rayDist(a, c, d) == 0);
    }
    return insideAngle(a, c, c + b - a, d) && ((b - a)^(d - c)) != 0;
}

bool segmentCross(point a, point b, point c, point d)
{
    if (a == b)
    {
        if (c == d)
        {
            return a == c;
        }
        return segmentDist(a, c, d) == 0;
    }
    if (c == d)
    {
        return segmentDist(c, a, b) == 0;
    }
    return rayCross(a, b, c, d) && rayCross(a, b, d, c) && rayCross(b, a, c, d) && rayCross(b, a, d, c);
}

bool check(point a, point b, point c, point d) {
    if (rayCross(a, b, c, d) || rayCross(b, a, c, d) || rayCross(a, b, d, c) || rayCross(b, a, d, c))
    {
        return 1;
    }
    return 0;
}

void solve() {
    int n;
    cin >> n;
    vector <point> a(n);
    for (int i = 0; i < n; ++i) {
        int l, r;
        cin >> l >> r;
        a[i].x = l;
        a[i].y = r;
    }
    int ans = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            for (int i1 = 0; i1 < n; ++i1) {
                for (int j1 = i1 + 1; j1 < n; ++j1) {
                    point a1 = a[i], b1 = a[j], c1 = a[i1], d1 = a[j1];
                    //cout << a1 << ' ' << b1 << ' '  << c1 << ' ' << d1;
                    if (check(a1, b1, c1, d1) && (i != i1 || j != j1)) {
                        ++ans;
                        //cout << a1 << ' ' << b1 << ' ' << c1 << ' ' << d1 << '\n';
                    }
                }
            }
        }
    }
    cout << ans / 2;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define int long long
#define double long double

struct point {
    int x, y;
};

int my_gcd(int a, int b) {
    if (b == 0) return a;
    return my_gcd(b, a % b);
}

pair <pair <int, int>, int> make_line(point a, point b) {
    if (a.x == b.x) {
        return {{1, 0}, -a.x};
    }
    if (a.y == b.y) return {{0, 1}, -a.y};
    int a1 = b.y - a.y, b1 = a.x - b.x, c1 = -(a1 * a.x + b1 * a.y);
    int g1 = my_gcd(max(a1, b1), min(a1, b1));
    int g = my_gcd(max(g1, c1), min(g1, c1));
    a1 /= g;
    b1 /= g;
    c1 /= g;
    return {{a1, b1}, c1};
}

void solve() {
    int n;
    cin >> n;
    vector <point> a(n);
    for (int i = 0; i < n; ++i) cin >> a[i].x >> a[i].y;
    map <pair <int, int>, int> ugols;
    set <pair <int, int> > u;
    set <pair <pair <int, int>, int> > lines;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            int _y = a[i].y - a[j].y, _x = a[i].x - a[j].x;
            auto res = make_line(a[i], a[j]);
            if (lines.find(res) == lines.end()) {
                int g = my_gcd(max(_x, _y), min(_x, _y));
                pair <int, int> ccc = {_x / g, _y / g};
                u.insert(ccc);
                if (ugols[ccc]) ++ugols[ccc];
                else ugols[ccc] = 1;
                lines.insert(res);
            }
        }
    }
    int sum = 0;
    for (auto elem : u) {
        sum += ugols[elem];
    }
    int ans = 0;
    //cout << sum << '\n';
    for (auto elem : u) {
        ans += ugols[elem] * (sum - ugols[elem]);
        //cout << ugols[elem] << ' ';
    }
    cout << ans / 2;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define int long long
#define double long double

struct point {
    int x, y;
};

int my_gcd(int a, int b) {
    if (b == 0) return a;
    return my_gcd(b, a % b);
}

pair <pair <int, int>, int> make_line(point a, point b) {
    if (a.x == b.x) {
        return {{1, 0}, -a.x};
    }
    if (a.y == b.y) return {{0, 1}, -a.y};
    int a1 = b.y - a.y, b1 = a.x - b.x, c1 = -(a1 * a.x + b1 * a.y);
    int g1 = my_gcd(max(abs(a1), abs(b1)), min(abs(a1), abs(b1)));
    int g = my_gcd(max(g1, abs(c1)), min(g1, abs(c1)));
    a1 /= g;
    b1 /= g;
    c1 /= g;
    if (b1 < 0) {
        a1 *= -1;
        b1 *= -1;
        c1 *= -1;
    }
    return {{a1, b1}, c1};
}

void solve() {
    int n;
    cin >> n;
    vector <point> a(n);
    for (int i = 0; i < n; ++i) cin >> a[i].x >> a[i].y;
    map <pair <int, int>, int> ugols;
    set <pair <int, int> > u;
    set <pair <pair <int, int>, int> > lines;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            int _y = a[i].y - a[j].y, _x = a[i].x - a[j].x;
            auto res = make_line(a[i], a[j]);
            if (lines.find(res) == lines.end()) {
                int g = my_gcd(max(abs(_x), abs(_y)), min(abs(_x), abs(_y)));
                if (_x < 0) {
                    _x *= -1;
                    _y *= -1;
                }
                pair <int, int> ccc = {_x / g, _y / g};
                u.insert(ccc);
                if (ugols[ccc]) ++ugols[ccc];
                else ugols[ccc] = 1;
                lines.insert(res);
            }
        }
    }
    int sum = 0;
    for (auto elem : u) {
        sum += ugols[elem];
    }
    int ans = 0;
    //cout << sum << '\n';
    for (auto elem : u) {
        ans += ugols[elem] * (sum - ugols[elem]);
        //cout << ugols[elem] << ' ';
    }
    cout << ans / 2;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define int long long
#define double long double

struct point {
    int x, y;
};

int my_gcd(int a, int b) {
    if (b == 0) return a;
    return my_gcd(b, a % b);
}

pair <pair <int, int>, int> make_line(point a, point b) {
    if (a.x == b.x) {
        return {{1, 0}, -a.x};
    }
    if (a.y == b.y) return {{0, 1}, -a.y};
    int a1 = b.y - a.y, b1 = a.x - b.x, c1 = -(a1 * a.x + b1 * a.y);
    int g1 = my_gcd(max(abs(a1), abs(b1)), min(abs(a1), abs(b1)));
    int g = my_gcd(max(g1, abs(c1)), min(g1, abs(c1)));
    a1 /= g;
    b1 /= g;
    c1 /= g;
    if (b1 < 0) {
        a1 *= -1;
        b1 *= -1;
        c1 *= -1;
    }
    return {{a1, b1}, c1};
}

void solve() {
    int n;
    cin >> n;
    vector <point> a(n);
    for (int i = 0; i < n; ++i) cin >> a[i].x >> a[i].y;
    map <pair <int, int>, int> ugols;
    set <pair <int, int> > u;
    set <pair <pair <int, int>, int> > lines;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            int _y = a[i].y - a[j].y, _x = a[i].x - a[j].x;
            auto res = make_line(a[i], a[j]);
            if (lines.find(res) == lines.end()) {
                int g = my_gcd(max(_x, _y), min(_x, _y));
                pair <int, int> ccc = {_x / g, _y / g};
                u.insert(ccc);
                if (ugols[ccc]) ++ugols[ccc];
                else ugols[ccc] = 1;
                lines.insert(res);
            }
        }
    }
    int sum = 0;
    for (auto elem : u) {
        sum += ugols[elem];
    }
    int ans = 0;
    //cout << sum << '\n';
    for (auto elem : u) {
        ans += ugols[elem] * (sum - ugols[elem]);
        //cout << ugols[elem] << ' ';
    }
    cout << ans / 2;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define int long long

struct point {
    int x, y;
};

void solve() {
    int n;
    cin >> n;
    vector <point> a(n);
    for (int i = 0; i < n; ++i) cin >> a[i].x >> a[i].y;
    map <double, int> ugols;
    set <double> u;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            double _y = a[i].y - a[j].y, _x = a[i].x - a[j].x;
            double ccc = atan2(_y, _x);
            u.insert(ccc);
            ugols[ccc]++;
        }
    }
    int sum = 0;
    for (auto elem : u) {
        sum += ugols[elem];
    }
    int ans = 0;
    for (auto elem : u) {
        ans += ugols[elem] * (sum - ugols[elem]);
    }
    cout << ans / 2;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define int long long
#define double long double

struct point {
    int x, y;
};

int my_gcd(int a, int b) {
    if (b == 0) return a;
    return my_gcd(b, a % b);
}

pair <pair <int, int>, int> make_line(point a, point b) {
    if (a.x == b.x) {
        return {{1, 0}, -a.x};
    }
    if (a.y == b.y) return {{0, 1}, -a.y};
    int a1 = b.y - a.y, b1 = a.x - b.x, c1 = -(a1 * a.x + b1 * a.y);
    int g1 = my_gcd(max(abs(a1), abs(b1)), min(abs(a1), abs(b1)));
    int g = my_gcd(max(g1, abs(c1)), min(g1, abs(c1)));
    a1 /= g;
    b1 /= g;
    c1 /= g;
    if (b1 < 0) {
        a1 *= -1;
        b1 *= -1;
        c1 *= -1;
    }
    return {{a1, b1}, c1};
}

void solve() {
    int n;
    cin >> n;
    vector <point> a(n);
    for (int i = 0; i < n; ++i) cin >> a[i].x >> a[i].y;
    map <pair <int, int>, int> ugols;
    set <pair <int, int> > u;
    set <pair <pair <int, int>, int> > lines;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            int _y = a[i].y - a[j].y, _x = a[i].x - a[j].x;
            auto res = make_line(a[i], a[j]);
            if (lines.find(res) == lines.end()) {
                int g = my_gcd(max(abs(_x), abs(_y)), min(abs(_x), abs(_y)));
                if (_y < 0 || (_y == 0 && _x < 0)) {
                    _x *= -1;
                    _y *= -1;
                }
                pair <int, int> ccc = {_x / g, _y / g};
                u.insert(ccc);
                if (ugols[ccc]) ++ugols[ccc];
                else ugols[ccc] = 1;
                lines.insert(res);
            }
        }
    }
    int sum = 0;
    for (auto elem : u) {
        sum += ugols[elem];
    }
    int ans = 0;
    //cout << sum << '\n';
    for (auto elem : u) {
        ans += ugols[elem] * (sum - ugols[elem]);
        //cout << ugols[elem] << ' ';
    }
    cout << ans / 2;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <unordered_set>
#include <sstream>
#include <cstring>
#include <iomanip>

int32_t gcd(int32_t a, int32_t b) {
	if(b == 0)
		return a;
	return gcd(b, a % b);
}

struct Line {
	int32_t x_shortened;
	int32_t y_shortened;
	int32_t point_x;
	int32_t point_y;
	long double y_at_x0;

	Line(int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
		point_x = x1;
		point_y = y1;

		x_shortened = x2 - x1;
		y_shortened = y2 - y1;

		if(x_shortened == 0) {
			x_shortened = 1;
			y_shortened = 40'000;
		}
		if(y_shortened == 0) {
			x_shortened = 40'000;
			y_shortened = 1;
		}

		int32_t gcd_fraction = gcd(x_shortened, y_shortened);
		x_shortened /= gcd_fraction;
		y_shortened /= gcd_fraction;

		if(y_shortened < 0) {
			x_shortened = -x_shortened;
			y_shortened = -y_shortened;
		}

		if(x_shortened == 1 && y_shortened == 40'000)
			y_at_x0 = point_x;
		else
			y_at_x0 = point_y - (long double)point_x / x_shortened * y_shortened;
	}

	bool operator <(Line& other) {
		int32_t lcm = y_shortened * other.y_shortened / gcd(y_shortened, other.y_shortened);
		if((x_shortened * lcm) / y_shortened != (other.x_shortened * lcm) / other.y_shortened)
			return (x_shortened * lcm) / y_shortened < (other.x_shortened * lcm) / other.y_shortened;
		return y_at_x0 < other.y_at_x0;
	}
};

struct Point {
	int32_t x;
	int32_t y;

	Point(int32_t x_, int32_t y_) {
		x = x_;
		y = y_;
	}
};

int main() {
	int32_t number_of_points;
	std::cin >> number_of_points;

	std::vector<Point> points;
	for(int32_t i = 0 ; i < number_of_points; i++) {
		int32_t x, y;
		std::cin >> x >> y;
		points.emplace_back(x, y);
	}

	std::vector<Line> lines;
	lines.reserve(number_of_points * number_of_points);
	for(int32_t i = 0; i < number_of_points; i++)
		for(int32_t j = i + 1; j < number_of_points; j++) {
			lines.emplace_back(points[i].x, points[i].y, points[j].x, points[j].y);
		}

	std::sort(lines.begin(), lines.end());

	std::vector<Line> lines2;
	lines2.reserve(number_of_points * number_of_points);
	lines2.push_back(lines[0]);
	for(int32_t i = 1 ;i < lines.size(); i++) {
		if (lines[i].x_shortened != lines[i - 1].x_shortened || lines[i].y_shortened != lines[i - 1].y_shortened) {
			lines2.push_back(lines[i]);
			continue;
		}
		if(fabsl(lines[i].y_at_x0 - lines[i - 1].y_at_x0) > 0.00001)
			lines2.push_back(lines[i]);
	}
	lines = lines2;

	int64_t answer = 0;
	int32_t group_size = 1;
	for(int32_t i = 1 ; i < lines.size(); i++) {
		if(lines[i].x_shortened == lines[i - 1].x_shortened && lines[i].y_shortened == lines[i - 1].y_shortened) {
			group_size++;
			continue;
		}
		answer += (lines.size() - group_size) * group_size;
		group_size = 1;
	}
	answer += (lines.size() - group_size) * group_size;
	std::cout << answer / 2;
	return 0;
}


#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <unordered_set>
#include <sstream>
#include <cstring>
#include <iomanip>

int32_t gcd(int32_t a, int32_t b) {
	if(b == 0)
		return a;
	return gcd(b, a % b);
}

struct Line {
	int32_t x_shortened;
	int32_t y_shortened;
	int32_t point_x;
	int32_t point_y;
	long double y_at_x0;

	Line(int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
		point_x = x1;
		point_y = y1;

		x_shortened = x2 - x1;
		y_shortened = y2 - y1;

		if(x_shortened == 0) {
			x_shortened = 1;
			y_shortened = 40'000;
		}
		if(y_shortened == 0) {
			x_shortened = 40'000;
			y_shortened = 1;
		}

		int32_t gcd_fraction = gcd(x_shortened, y_shortened);
		x_shortened /= gcd_fraction;
		y_shortened /= gcd_fraction;

		if(y_shortened < 0) {
			x_shortened = -x_shortened;
			y_shortened = -y_shortened;
		}

		if(x_shortened == 1 && y_shortened == 40'000)
			y_at_x0 = point_x;
		else if(x_shortened == 40'000 && y_shortened == 1) {
			y_at_x0 = point_y;
		} else
			y_at_x0 = point_y - (long double)point_x / x_shortened * y_shortened;
	}

	bool operator <(Line& other) {
		int32_t lcm = y_shortened * other.y_shortened / gcd(y_shortened, other.y_shortened);
		if((x_shortened * lcm) / y_shortened != (other.x_shortened * lcm) / other.y_shortened)
			return (x_shortened * lcm) / y_shortened < (other.x_shortened * lcm) / other.y_shortened;
		return y_at_x0 < other.y_at_x0;
	}
};

struct Point {
	int32_t x;
	int32_t y;

	Point(int32_t x_, int32_t y_) {
		x = x_;
		y = y_;
	}
};

int main() {
	int32_t number_of_points;
	std::cin >> number_of_points;

	std::vector<Point> points;
	for(int32_t i = 0 ; i < number_of_points; i++) {
		int32_t x, y;
		std::cin >> x >> y;
		points.emplace_back(x, y);
	}

	std::vector<Line> lines;
	lines.reserve(number_of_points * number_of_points);
	for(int32_t i = 0; i < number_of_points; i++)
		for(int32_t j = i + 1; j < number_of_points; j++) {
			lines.emplace_back(points[i].x, points[i].y, points[j].x, points[j].y);
		}

	std::sort(lines.begin(), lines.end());

	std::vector<Line> lines2;
	lines2.reserve(number_of_points * number_of_points);
	lines2.push_back(lines[0]);
	for(int32_t i = 1 ;i < lines.size(); i++) {
		if (lines[i].x_shortened != lines[i - 1].x_shortened || lines[i].y_shortened != lines[i - 1].y_shortened) {
			lines2.push_back(lines[i]);
			continue;
		}
		if(fabsl(lines[i].y_at_x0 - lines[i - 1].y_at_x0) > 0.00001)
			lines2.push_back(lines[i]);
	}
	lines = lines2;

	int64_t answer = 0;
	int32_t group_size = 1;
	for(int32_t i = 1 ; i < lines.size(); i++) {
		if(lines[i].x_shortened == lines[i - 1].x_shortened && lines[i].y_shortened == lines[i - 1].y_shortened) {
			group_size++;
			continue;
		}
		answer += (lines.size() - group_size) * group_size;
		group_size = 1;
	}
	answer += (lines.size() - group_size) * group_size;
	std::cout << answer / 2;
	return 0;
}


#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <unordered_set>
#include <sstream>
#include <cstring>
#include <iomanip>

int32_t gcd(int32_t a, int32_t b) {
	if(b == 0)
		return a;
	return gcd(b, a % b);
}

struct Line {
	int32_t x_shortened;
	int32_t y_shortened;
	int32_t point_x;
	int32_t point_y;
	long double y_at_x0;

	Line(int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
		point_x = x1;
		point_y = y1;

		x_shortened = x2 - x1;
		y_shortened = y2 - y1;

		if(x_shortened == 0) {
			x_shortened = 1;
			y_shortened = 40'000;
		}
		if(y_shortened == 0) {
			x_shortened = 40'000;
			y_shortened = 1;
		}

		int32_t gcd_fraction = gcd(x_shortened, y_shortened);
		x_shortened /= gcd_fraction;
		y_shortened /= gcd_fraction;

		if(y_shortened < 0) {
			x_shortened = -x_shortened;
			y_shortened = -y_shortened;
		}

		if(x_shortened == 1 && y_shortened == 40'000)
			y_at_x0 = point_x;
		else if(x_shortened == 40'000 && y_shortened == 1) {
			y_at_x0 = point_y;
		} else
			y_at_x0 = point_y - (long double)point_x / x_shortened * y_shortened;
	}

	bool operator <(Line& other) {
		int32_t lcm = y_shortened * other.y_shortened / gcd(y_shortened, other.y_shortened);
		if(((int64_t)x_shortened * lcm) / y_shortened != ((int64_t)other.x_shortened * lcm) / other.y_shortened)
			return ((int64_t)x_shortened * lcm) / y_shortened < ((int64_t)other.x_shortened * lcm) / other.y_shortened;
		return y_at_x0 < other.y_at_x0;
	}
};

struct Point {
	int32_t x;
	int32_t y;

	Point(int32_t x_, int32_t y_) {
		x = x_;
		y = y_;
	}
};

int main() {
	int32_t number_of_points;
	std::cin >> number_of_points;

	std::vector<Point> points;
	for(int32_t i = 0 ; i < number_of_points; i++) {
		int32_t x, y;
		std::cin >> x >> y;
		points.emplace_back(x, y);
	}

	std::vector<Line> lines;
	lines.reserve(number_of_points * number_of_points);
	for(int32_t i = 0; i < number_of_points; i++)
		for(int32_t j = i + 1; j < number_of_points; j++) {
			lines.emplace_back(points[i].x, points[i].y, points[j].x, points[j].y);
		}

	std::sort(lines.begin(), lines.end());

	std::vector<Line> lines2;
	lines2.reserve(number_of_points * number_of_points);
	lines2.push_back(lines[0]);
	for(int32_t i = 1 ;i < lines.size(); i++) {
		if (lines[i].x_shortened != lines[i - 1].x_shortened || lines[i].y_shortened != lines[i - 1].y_shortened) {
			lines2.push_back(lines[i]);
			continue;
		}
		if(fabsl(lines[i].y_at_x0 - lines[i - 1].y_at_x0) > 0.00001)
			lines2.push_back(lines[i]);
	}
	lines = lines2;

	int64_t answer = 0;
	int32_t group_size = 1;
	for(int32_t i = 1 ; i < lines.size(); i++) {
		if(lines[i].x_shortened == lines[i - 1].x_shortened && lines[i].y_shortened == lines[i - 1].y_shortened) {
			group_size++;
			continue;
		}
		answer += (lines.size() - group_size) * group_size;
		group_size = 1;
	}
	answer += (lines.size() - group_size) * group_size;
	std::cout << answer / 2;
	return 0;
}


#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <unordered_set>
#include <sstream>
#include <cstring>
#include <iomanip>

int32_t gcd(int32_t a, int32_t b) {
	if(b == 0)
		return a;
	return gcd(b, a % b);
}

struct Line {
	int32_t x_shortened;
	int32_t y_shortened;
	int32_t point_x;
	int32_t point_y;
	long double y_at_x0;

	Line(int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
		point_x = x1;
		point_y = y1;

		x_shortened = x2 - x1;
		y_shortened = y2 - y1;

		if(x_shortened == 0) {
			x_shortened = 1;
			y_shortened = 40'000;
		}
		if(y_shortened == 0) {
			x_shortened = 40'000;
			y_shortened = 1;
		}

		int32_t gcd_fraction = gcd(x_shortened, y_shortened);
		x_shortened /= gcd_fraction;
		y_shortened /= gcd_fraction;

		if(y_shortened < 0) {
			x_shortened = -x_shortened;
			y_shortened = -y_shortened;
		}

		if(x_shortened == 1 && y_shortened == 40'000)
			y_at_x0 = point_x;
		else if(x_shortened == 40'000 && y_shortened == 1) {
			y_at_x0 = point_y;
		} else
			y_at_x0 = point_y - (long double)point_x / x_shortened * y_shortened;
	}

	bool operator <(Line& other) {
		int32_t lcm = y_shortened * other.y_shortened / gcd(y_shortened, other.y_shortened);
		if((int64_t)(x_shortened * lcm) / y_shortened != (int64_t)(other.x_shortened * lcm) / other.y_shortened)
			return (int64_t)(x_shortened * lcm) / y_shortened < (int64_t)(other.x_shortened * lcm) / other.y_shortened;
		return y_at_x0 < other.y_at_x0;
	}
};

struct Point {
	int32_t x;
	int32_t y;

	Point(int32_t x_, int32_t y_) {
		x = x_;
		y = y_;
	}
};

int main() {
	int32_t number_of_points;
	std::cin >> number_of_points;

	std::vector<Point> points;
	for(int32_t i = 0 ; i < number_of_points; i++) {
		int32_t x, y;
		std::cin >> x >> y;
		points.emplace_back(x, y);
	}

	std::vector<Line> lines;
	lines.reserve(number_of_points * number_of_points);
	for(int32_t i = 0; i < number_of_points; i++)
		for(int32_t j = i + 1; j < number_of_points; j++) {
			lines.emplace_back(points[i].x, points[i].y, points[j].x, points[j].y);
		}

	std::sort(lines.begin(), lines.end());

	std::vector<Line> lines2;
	lines2.reserve(number_of_points * number_of_points);
	lines2.push_back(lines[0]);
	for(int32_t i = 1 ;i < lines.size(); i++) {
		if (lines[i].x_shortened != lines[i - 1].x_shortened || lines[i].y_shortened != lines[i - 1].y_shortened) {
			lines2.push_back(lines[i]);
			continue;
		}
		if(fabsl(lines[i].y_at_x0 - lines[i - 1].y_at_x0) > 0.00001)
			lines2.push_back(lines[i]);
	}
	lines = lines2;

	int64_t answer = 0;
	int32_t group_size = 1;
	for(int32_t i = 1 ; i < lines.size(); i++) {
		if(lines[i].x_shortened == lines[i - 1].x_shortened && lines[i].y_shortened == lines[i - 1].y_shortened) {
			group_size++;
			continue;
		}
		answer += (lines.size() - group_size) * group_size;
		group_size = 1;
	}
	answer += (lines.size() - group_size) * group_size;
	std::cout << answer / 2;
	return 0;
}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <cstring>
#include <string.h>
#include <sstream>
#include <iomanip>
#include <queue>
#include <stack>
#include <deque>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <tuple>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

typedef unsigned long ul;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const ll MOD = 1e9+7;
const ll CFMOD = 998244353;
const double PI  = 3.14159265358;
const double EPS = 1e-4;

#define INT_MX 2147483647
#define INF ((int)1e9)
#define LLINF ((ll)1e18)
#define F first
#define S second
#define MP(x,y) make_pair(x,y)
#define sz(v) ((int)v.size())
#define rs(n) resize(n)
#define ALL(v) v.begin(),v.end()
#define reset(v) memset((v),0,sizeof(v))
#define EB emplace_back
#define PB push_back
#define PF push_front
#define rep(i,n) for(int i=0;i<(n);i++)
#define rep1(i,n) for(int i=1;i<=(n);i++)
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define vec vector
#define __ <<' '<<
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

struct line{
    int a, b, c;

    bool operator<(const line& obj)const{
        if(a != obj.a)  return a < obj.a;
        if(b != obj.b)  return b < obj.b;
        return c < obj.c;
    }
};

int gcd(int a, int b){
    if(b == 0)  return a;
    return gcd(b, a%b);
}

line find_line(pii x, pii y){
    line res;
    res.a = x.S - y.S;
    res.b = y.F - x.F;
    res.c = - res.a * x.F - res.b * x.S;

    int tmp = gcd(gcd(res.a, res.b), res.c);
    res.a /= tmp;
    res.b /= tmp;
    res.c /= tmp;

    return res;
}

bool parallel(line l1, line l2){
    if(l1.b == 0 || l2.b == 0){
        if(l1.b == 0 && l2.b == 0)  return true;
        else                        return false;
    }

    long double x, y;
    x = l1.a;
    y = l2.a;

    x /= l1.b;
    y /= l2.b;

    if(abs(x-y) < EPS)
        return true;
    else
        return false;
}

void solve(){
    int n;
    ll ans = 0;
    vec<pii> pt;
    set<line> st;
    line tmp;

    cin >> n;
    pt.rs(n);
    rep(i,n)
        cin >> pt[i].F >> pt[i].S;

    REP(i,1,n){
        rep(j,i){
            tmp = find_line(pt[j], pt[i]);
            if(st.count(tmp))   continue;
            for(auto u:st) if(!parallel(u, tmp))
                ans++;
            st.insert(tmp);
        }
    }

    cout << ans << '\n';

}

int main(){
    int t = 1;

    // cin >> t;
    while(t--){
        solve();
    }
}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <cstring>
#include <string.h>
#include <sstream>
#include <iomanip>
#include <queue>
#include <stack>
#include <deque>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <tuple>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

typedef unsigned long ul;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const ll MOD = 1e9+7;
const ll CFMOD = 998244353;
const double PI  = 3.14159265358;
const double EPS = 1e-6;

#define INT_MX 2147483647
#define INF ((int)1e9)
#define LLINF ((ll)1e18)
#define F first
#define S second
#define MP(x,y) make_pair(x,y)
#define sz(v) ((int)v.size())
#define rs(n) resize(n)
#define ALL(v) v.begin(),v.end()
#define reset(v) memset((v),0,sizeof(v))
#define EB emplace_back
#define PB push_back
#define PF push_front
#define rep(i,n) for(int i=0;i<(n);i++)
#define rep1(i,n) for(int i=1;i<=(n);i++)
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define vec vector
#define __ <<' '<<
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

struct line{
    long double a, b;
    ll c;

    bool operator<(const line& obj)const{
        if(a != obj.a)  return a < obj.a;
        if(b != obj.b)  return b < obj.b;
        return c < obj.c;
    }
};

line find_line(pii x, pii y){
    line res;
    res.a = x.S - y.S;
    res.b = y.F - x.F;
    ll tmp;
    tmp = -res.a;
    tmp *= x.F;
    res.c = -res.b;
    res.c *= x.S;
    res.c += tmp;

    return res;
}

bool parallel(line l1, line l2){
    if(l1.b == 0 || l2.b == 0){
        if(l1.b == 0 && l2.b == 0)  return true;
        else                        return false;
    }

    if(abs((l1.a/l1.b)-(l2.a/l2.b)) < EPS)
        return true;
    else
        return false;
}

void solve(){
    int n;
    ll ans = 0;
    vec<pll> pt;
    set<line> st;
    line tmp;

    cin >> n;
    pt.rs(n);
    rep(i,n)
        cin >> pt[i].F >> pt[i].S;

    REP(i,1,n){
        rep(j,i){
            tmp = find_line(pt[j], pt[i]);
            if(st.count(tmp))   continue;
            for(auto u:st) if(!parallel(u, tmp))
                ans++;
            st.insert(tmp);
        }
    }

    cout << ans << '\n';

}

int main(){
    int t = 1;

    // cin >> t;
    while(t--){
        solve();
    }
}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <cstring>
#include <string.h>
#include <sstream>
#include <iomanip>
#include <queue>
#include <stack>
#include <deque>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <tuple>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

typedef unsigned long ul;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const ll MOD = 1e9+7;
const ll CFMOD = 998244353;
const double PI  = 3.14159265358;
const double EPS = 1e-6;

#define INT_MX 2147483647
#define INF ((int)1e9)
#define LLINF ((ll)1e18)
#define F first
#define S second
#define MP(x,y) make_pair(x,y)
#define sz(v) ((int)v.size())
#define rs(n) resize(n)
#define ALL(v) v.begin(),v.end()
#define reset(v) memset((v),0,sizeof(v))
#define EB emplace_back
#define PB push_back
#define PF push_front
#define rep(i,n) for(int i=0;i<(n);i++)
#define rep1(i,n) for(int i=1;i<=(n);i++)
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define vec vector
#define __ <<' '<<
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

int __gcd(int x, int y){
    if(y == 0)  return x;
    return __gcd(y, x%y);
}

void solve(){
    int n;

    cin >> n;

    vec<pii> ipt(n);
    map<pii, set<ll>> mp;
    map<pii, ll> tot;
    pii tmp;
    int gcd;
    ll ans = 0, sum = 0;

    rep(i,n){
        cin >> ipt[i].F >> ipt[i].S;

        rep(j,i){
            tmp = MP(ipt[i].S - ipt[j].S, ipt[j].F - ipt[i].F);
            gcd = __gcd(tmp.F, tmp.S);
            tmp.F /= gcd;
            tmp.S /= gcd;

            if(tmp.F < 0 || (tmp.F == 0 && tmp.S < 0)){
                tmp.F *= -1;
                tmp.S *= -1;
            }

            ll c = 1LL * tmp.F * ipt[j].F + 1LL * tmp.S * ipt[j].S;

            if(!mp[tmp].count(c)){
                mp[tmp].insert(c);
                ans += sum - tot[tmp];
                tot[tmp]++;
                sum++;
            }
        }
    }
    cout << ans << '\n';

}

int main(){
    int t = 1;

    // cin >> t;
    while(t--){
        solve();
    }
}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <cstring>
#include <string.h>
#include <sstream>
#include <iomanip>
#include <queue>
#include <stack>
#include <deque>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <tuple>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

typedef unsigned long ul;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const ll MOD = 1e9+7;
const ll CFMOD = 998244353;
const double PI  = 3.14159265358;
const double EPS = 1e-6;

#define INT_MX 2147483647
#define INF ((int)1e9)
#define LLINF ((ll)1e18)
#define F first
#define S second
#define MP(x,y) make_pair(x,y)
#define sz(v) ((int)v.size())
#define rs(n) resize(n)
#define ALL(v) v.begin(),v.end()
#define reset(v) memset((v),0,sizeof(v))
#define EB emplace_back
#define PB push_back
#define PF push_front
#define rep(i,n) for(int i=0;i<(n);i++)
#define rep1(i,n) for(int i=1;i<=(n);i++)
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define vec vector
#define __ <<' '<<
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

struct line{
    int a, b, c;

    bool operator<(const line& obj)const{
        if(a != obj.a)  return a < obj.a;
        if(b != obj.b)  return b < obj.b;
        return c < obj.c;
    }
};

int gcd(int a, int b){
    if(b == 0)  return a;
    return gcd(b, a%b);
}

line find_line(pii x, pii y){
    line res;
    res.a = x.S - y.S;
    res.b = y.F - x.F;
    res.c = - res.a * x.F - res.b * x.S;

    int tmp = gcd(gcd(res.a, res.b), res.c);
    res.a /= tmp;
    res.b /= tmp;
    res.c /= tmp;

    return res;
}

bool parallel(line l1, line l2){
    if(l1.b == 0 || l2.b == 0){
        if(l1.b == 0 && l2.b == 0)  return true;
        else                        return false;
    }

    long double x, y;
    x = l1.a;
    y = l2.a;

    x /= l1.b;
    y /= l2.b;

    if(abs(x-y) < EPS)
        return true;
    else
        return false;
}

void solve(){
    int n;
    ll ans = 0;
    vec<pii> pt;
    set<line> st;
    line tmp;

    cin >> n;
    pt.rs(n);
    rep(i,n)
        cin >> pt[i].F >> pt[i].S;

    REP(i,1,n){
        rep(j,i){
            tmp = find_line(pt[j], pt[i]);
            if(st.count(tmp))   continue;
            for(auto u:st) if(!parallel(u, tmp))
                ans++;
            st.insert(tmp);
        }
    }

    cout << ans << '\n';

}

int main(){
    int t = 1;

    // cin >> t;
    while(t--){
        solve();
    }
}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <cstring>
#include <string.h>
#include <sstream>
#include <iomanip>
#include <queue>
#include <stack>
#include <deque>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <tuple>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

typedef unsigned long ul;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const ll MOD = 1e9+7;
const ll CFMOD = 998244353;
const double PI  = 3.14159265358;
const double EPS = 1e-6;

#define INT_MX 2147483647
#define INF ((int)1e9)
#define LLINF ((ll)1e18)
#define F first
#define S second
#define MP(x,y) make_pair(x,y)
#define sz(v) ((int)v.size())
#define rs(n) resize(n)
#define ALL(v) v.begin(),v.end()
#define reset(v) memset((v),0,sizeof(v))
#define EB emplace_back
#define PB push_back
#define PF push_front
#define rep(i,n) for(int i=0;i<(n);i++)
#define rep1(i,n) for(int i=1;i<=(n);i++)
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define vec vector
#define __ <<' '<<
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

struct line{
    long double a, b;
    ll c;

    bool operator<(const line& obj)const{
        if(a != obj.a)  return a < obj.a;
        if(b != obj.b)  return b < obj.b;
        return c < obj.c;
    }
};

ll gcd(int a, int b){
    if(b == 0)  return a;
    return gcd(b, a%b);
}

line find_line(pii x, pii y){
    line res;
    res.a = x.S - y.S;
    res.b = y.F - x.F;
    ll tmp;
    tmp = -res.a;
    tmp *= x.F;
    res.c = -res.b;
    res.c *= x.S;
    res.c += tmp;

    int GCD = gcd(res.a, gcd(res.b, res.c));
    res.a /= GCD;
    res.b /= GCD;
    res.c /= GCD;

    return res;
}

bool parallel(line l1, line l2){
    if(l1.b == 0 || l2.b == 0){
        if(l1.b == 0 && l2.b == 0)  return true;
        else                        return false;
    }

    if(abs((l1.a/l1.b)-(l2.a/l2.b)) < EPS)
        return true;
    else
        return false;
}

void solve(){
    int n;
    ll ans = 0;
    vec<pll> pt;
    set<line> st;
    line tmp;

    cin >> n;
    pt.rs(n);
    rep(i,n)
        cin >> pt[i].F >> pt[i].S;

    REP(i,1,n){
        rep(j,i){
            tmp = find_line(pt[j], pt[i]);
            if(st.count(tmp))   continue;
            for(auto u:st) if(!parallel(u, tmp))
                ans++;
            st.insert(tmp);
        }
    }

    cout << ans << '\n';

}

int main(){
    int t = 1;

    // cin >> t;
    while(t--){
        solve();
    }
}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <cstring>
#include <string.h>
#include <sstream>
#include <iomanip>
#include <queue>
#include <stack>
#include <deque>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <tuple>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

typedef unsigned long ul;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const ll MOD = 1e9+7;
const ll CFMOD = 998244353;
const double PI  = 3.14159265358;
const double EPS = 1e-6;

#define INT_MX 2147483647
#define INF ((int)1e9)
#define LLINF ((ll)1e18)
#define F first
#define S second
#define MP(x,y) make_pair(x,y)
#define sz(v) ((int)v.size())
#define rs(n) resize(n)
#define ALL(v) v.begin(),v.end()
#define reset(v) memset((v),0,sizeof(v))
#define EB emplace_back
#define PB push_back
#define PF push_front
#define rep(i,n) for(int i=0;i<(n);i++)
#define rep1(i,n) for(int i=1;i<=(n);i++)
#define REP(i,a,b) for(int i=(a);i<(b);i++)
#define vec vector
#define __ <<' '<<
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

struct line{
    int a, b, c;

    bool operator<(const line& obj)const{
        return a > obj.a || (a == obj.a && (b > obj.b));
    }
};

int gcd(int a, int b){
    if(b == 0)  return a;
    return gcd(b, a%b);
}

line find_line(pii x, pii y){
    line res;
    res.a = x.S - y.S;
    res.b = y.F - x.F;
    res.c = - res.a * x.F - res.b * x.S;

    int tmp = gcd(gcd(res.a, res.b), res.c);
    res.a /= tmp;
    res.b /= tmp;
    res.c /= tmp;

    return res;
}

bool parallel(line l1, line l2){
    if(l1.b == 0 || l2.b == 0){
        if(l1.b == 0 && l2.b == 0)  return true;
        else                        return false;
    }

    long double x, y;
    x = l1.a;
    y = l2.a;

    x /= l1.b;
    y /= l2.b;

    if(abs(x-y) < EPS)
        return true;
    else
        return false;
}

void solve(){
    int n;
    ll ans = 0;
    vec<pii> pt;
    set<line> st;
    line tmp;

    cin >> n;
    pt.rs(n);
    rep(i,n)
        cin >> pt[i].F >> pt[i].S;

    REP(i,1,n){
        rep(j,i){
            tmp = find_line(pt[j], pt[i]);
            if(st.count(tmp))   continue;
            for(auto u:st) if(!parallel(u, tmp))
                ans++;
            st.insert(tmp);
        }
    }

    cout << ans << '\n';

}

int main(){
    int t = 1;

    // cin >> t;
    while(t--){
        solve();
    }
}


#include "bits/stdc++.h"
using namespace std;
#define fast ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL)
const int mod = 1e9 + 7;
#define F first
#define int long long
#define S second
int gcd(int x, int y) {
    x = abs(x), y = abs(y);
    while (x && y) {
        if (x >= y) {
            x %= y;
        }
        else {
            y %= x;
        }
    }
    return x + y;
}
struct node {
    int x, y, Const;
    node(int a, int b, int c) : x(a), y(b), Const(c){};
    bool operator <(const node b) const {
        if (x != b.x) {
            return x < b.x;
        }
        if (y != b.y) {
            return y < b.y;
        }
        return Const < b.Const;
    }
};
map < pair < int, int >, int > mp;
node get(int x1, int y1, int x2, int y2) {
    int cx = y1 - y2;
    int cy = x2 - x1;
    int c = x1*y2 - y1*x2;
    int g = (gcd(cx, gcd(cy, c)));
    cx /= g, cy /= g, c /= g;
    if (cx < 0 || (cx == 0 && cy < 0)) {
        cx *= -1, cy *= -1, c *= -1;
    }
    cout << cx << ' ' << cy << ' ' << c << '\n';
    return node((cx), (cy), (c));

}
void sub(int x, int y) {
    mp[{x, y}] += 1;
}
signed main() {
    fast;
    int n;
    cin >> n;
    pair < int, int > v[n];
    for (int i = 0; i < n; ++i) {
        cin >> v[i].first >> v[i].second;
    }
    set < node > s;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            s.insert(get(v[i].first, v[i].second, v[j].first, v[j].second));
        }
    }
    int ans = s.size();
    for (auto i : s) {
        sub(i.x, i.y);
    }
    int cnt = 0;
    for (auto i : mp) {
        cnt += (i.second * (i.second - 1) / 2);
    }
    cout << max(0LL, ans * (ans - 1) / 2 - cnt);
    return 0;
}


#include "bits/stdc++.h"
using namespace std;
#define fast ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL)
const int mod = 1e9 + 7;
#define F first
#define int long long
#define S second
int gcd(int x, int y) {
	x = abs(x), y = abs(y);
	while (x && y) {
		if (x >= y) {
			x %= y;
		}
		else {
			y %= x;
		}
	}
	return x + y;
}
struct node {
	int x, y, Const;
	node(int a, int b, int c) : x(a), y(b), Const(c){};
	bool operator <(const node b) const {
		if (x != b.x) {
			return x < b.x;
		}
		if (y != b.y) {
			return y < b.y;
		}
		return Const < b.Const;
	}
};
map < pair < int, int >, int > mp;
node get(int x1, int y1, int x2, int y2) {
	int cx = y1 - y2;
	int cy = x2 - x1;
	int c = x1*y2 - y1*x2;
	int f = cx < 0 ? -1 : 1;
	cx *= f, cy *= f, c *= f;
	int g = gcd(cx, gcd(cy, c));
	cx /= g, cy /= g, c /= g;
	return node(cy, cx, c);
}
void sub(int x, int y) {
	mp[{x, y}] += 1;
}
signed main() {
	fast;
	int n;
	cin >> n;
	pair < int, int > v[n];
	for (int i = 0; i < n; ++i) {
		cin >> v[i].first >> v[i].second;
	}
	set < node > s;
	for (int i = 0; i < n; ++i) {
		for (int j = i + 1; j < n; ++j) {
			s.insert(get(v[i].first, v[i].second, v[j].first, v[j].second));
		}
	}
	int ans = s.size();
	for (auto i : s) {
		sub(i.x, i.y);
	}
	// cout << "gf " << gcd(2, gcd(0))
	int cnt = 0;
	for (auto i : mp) {
		cnt += (i.second * (i.second - 1) / 2);
	}
	cout << max(0LL, ans * (ans - 1) / 2 - cnt);
	return 0;
}


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

#define fast ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL)
const int mod = 1e9 + 7;
#define F first
#define S second

int gcd(int x, int y) {
	if (!x and !y) {
		return 1;
	}
	if (x < 0) {
		x *= -1;
	}
	if (y < 0) {
		y *= -1;
	}
	while (x && y) {
		if (x >= y) {
			x %= y;
		}
		else {
			y %= x;
		}
	}
	return x + y;
}

struct node {
	int x, y, Const;
	node(int a, int b, int c) : x(a), y(b), Const(c){};
	bool operator <(const node b) const {
		if(x != b.x)
			return x < b.x;
		if(y != b.y)
			return y < b.y;
		return Const < b.Const;
	}
};
map < pair < int, int >, int > mp;

node get(int x1, int y1, int x2, int y2) {
	int g = gcd(x2-x1, gcd(y2-y1, y1*x2 - x1*y2));
	int f = (x2 - x1) < 0 ? -1 : 1;
	int x = (x2-x1)/g*f, y = (y2-y1)/g*f;
	return node(x, y, f*(y1*x2 - x1*y2));
}

void sub(int x, int y) {
	int g2 = gcd(x, y);
	mp[{x/g2, y/g2}] += 1;
}

signed main() {
	fast;
	int n;
	cin >> n;
	pair < int, int > v[n];
	for (int i = 0; i < n; ++i) {
		cin >> v[i].first >> v[i].second;
	}

	set < node > s;

	for (int i = 0; i < n; ++i) {
		for (int j = i + 1; j < n; ++j) {
			s.insert(get(v[i].first, v[i].second, v[j].first, v[j].second));
		}
	}

	int ans = s.size();
	for (auto i : s) {
		sub(i.x, i.y);
	}
	// cout << "Ends here\n";
	// cout << ans << '\n';
	int cnt = 0;
	for (auto i : mp) {
		// cout << i.first.first << ' ' << i.first.second << ' ' << i.second << '\n';
		cnt += (i.second * (i.second - 1) / 2);
	}
	// cout << cnt << '\n';
	cout << max(0, ans * (ans - 1) / 2 - cnt);

	return 0;
}


#include "bits/stdc++.h"
using namespace std;
#define fast ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL)
const int mod = 1e9 + 7;
#define F first
#define int long long
#define S second
int gcd(int x, int y) {
	x = abs(x), y = abs(y);
	while (x && y) {
		if (x >= y) {
			x %= y;
		}
		else {
			y %= x;
		}
	}
	return x + y;
}
struct node {
	int x, y, Const;
	node(int a, int b, int c) : x(a), y(b), Const(c){};
	bool operator <(const node b) const {
		if (x != b.x) {
			return x < b.x;
		}
		if (y != b.y) {
			return y < b.y;
		}
		return Const < b.Const;
	}
};
map < pair < int, int >, set < int > > mp;
inline void get(int x1, int y1, int x2, int y2) {
	int cx = y2 - y1;
	int cy = x1 - x2;
	int cst = x2*y1 - x1*y2;
	int g = gcd(cx, gcd(cy, cst));
	cx /= g, cy /= g, cst /= g;
	if (cx < 0) {
		cx *= -1, cy *= -1, cst *= -1;
	}
	mp[{cx, cy}].insert(cst);
}
signed main() {
	fast;
	int n;
	cin >> n;
	pair < int, int > v[n];
	for (int i = 0; i < n; ++i) {
		cin >> v[i].first >> v[i].second;
	}
	for (int i = 0; i < n; ++i) {
		for (int j = i + 1; j < n; ++j) {
			get(v[i].first, v[i].second, v[j].first, v[j].second);
		}
	}
	int cnt = 0, ans = 0;;
	for (auto i : mp) {
		int x = i.second.size();
		cnt += x * (x - 1) / 2;
		ans += x;
	}
	cout << max(0LL, ans * (ans - 1) / 2 - cnt);
	return 0;
}


#include "bits/stdc++.h"
using namespace std;
#define fast ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL)
const int mod = 1e9 + 7;
#define F first
#define int long long
#define S second
int gcd(int x, int y) {
    x = abs(x), y = abs(y);
    while (x && y) {
        if (x >= y) {
            x %= y;
        }
        else {
            y %= x;
        }
    }
    return x + y;
}
struct node {
    int x, y, Const;
    node(int a, int b, int c) : x(a), y(b), Const(c){};
    bool operator <(const node b) const {
        if (x != b.x) {
            return x < b.x;
        }
        if (y != b.y) {
            return y < b.y;
        }
        return Const < b.Const;
    }
};
map < pair < int, int >, int > mp;
node get(int x1, int y1, int x2, int y2) {
    int cx = y1 - y2;
    int cy = x2 - x1;
    int c = x1*y2 - y1*x2;
    int g = (gcd(cx, gcd(cy, c)));
    cx /= g, cy /= g, c /= g;
    if (cx < 0 || (cx == 0 && cy < 0)) {
        cx *= -1, cy *= -1, c *= -1;
    }
    return node((cx), (cy), (c));

}
void sub(int x, int y) {
    mp[{x, y}] += 1;
}
signed main() {
    fast;
    int n;
    cin >> n;
    pair < int, int > v[n];
    for (int i = 0; i < n; ++i) {
        cin >> v[i].first >> v[i].second;
    }
    set < node > s;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            s.insert(get(v[i].first, v[i].second, v[j].first, v[j].second));
        }
    }
    int ans = s.size();
    for (auto i : s) {
        sub(i.x, i.y);
    }
    int cnt = 0;
    for (auto i : mp) {
        cnt += (i.second * (i.second - 1) / 2);
    }
    cout << max(0LL, ans * (ans - 1) / 2 - cnt);
    return 0;
}


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

#define fast ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL)
const int mod = 1e9 + 7;
#define F first
#define int long
#define S second

int gcd(int x, int y) {
	if (!x and !y) {
		return 0;
	}
	if (x < 0) {
		x *= -1;
	}
	if (y < 0) {
		y *= -1;
	}
	while (x && y) {
		if (x >= y) {
			x %= y;
		}
		else {
			y %= x;
		}
	}
	return x + y;
}

struct node {
	int x, y, Const;
	node(int a, int b, int c) : x(a), y(b), Const(c){};
	bool operator <(const node b) const {
		if(x != b.x)
			return x < b.x;
		if(y != b.y)
			return y < b.y;
		return Const < b.Const;
	}
};
map < pair < int, int >, int > mp;

node get(int x1, int y1, int x2, int y2) {
	int g = gcd(x2-x1, gcd(y2-y1, y1*x2 - x1*y2));
	if (!g) {
		g = 1;
	}
	int f = (x2 - x1) < 0 ? -1 : 1;
	int x = (x2-x1)/g*f, y = (y2-y1)/g*f;
	return node(x, y, (y1*x2 - x1*y2)/g*f);
}

void sub(int x, int y) {
	int g2 = max(1L, gcd(x, y));
	mp[{x/g2, y/g2}] += 1;
}

signed main() {
	fast;
	int n;
	cin >> n;
	pair < int, int > v[n];
	for (int i = 0; i < n; ++i) {
		cin >> v[i].first >> v[i].second;
	}

	set < node > s;

	for (int i = 0; i < n; ++i) {
		for (int j = i + 1; j < n; ++j) {
			s.insert(get(v[i].first, v[i].second, v[j].first, v[j].second));
		}
	}

	int ans = s.size();
	// cout << ans << '\n';
	for (auto i : s) {
		// cout << i.x << ' ' << i.y << ' ' << i.Const << '\n';
		sub(i.x, i.y);
	}
	// cout << "gf " << gcd(2, gcd(0))
	int cnt = 0;
	for (auto i : mp) {
		cnt += (i.second * (i.second - 1) / 2);
	}
	cout << max(0L, ans * (ans - 1) / 2 - cnt);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111], n;
map<pair<ll,ll>, set<ll>> line;
void solve()
{
    scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", &x[i], &y[i]);
    for(int i=0;i<n;++i) for(int j=i+1;j<n;++j)
    {
        ll dx = x[i] - x[j];
        ll dy = y[i] - y[j];
        ll g = __gcd(dy, dx);
        dx /=g;
        dy /=g;
        ll s = dy*x[i] - dx * y[i];
        line[{dy, dx}].insert(s);
    }
    ll r = 0;
    ll ans = 0;
    for(auto it : line)
    {
        ans += 1LL*it.second.size()*r;
        r += 1LL*it.second.size();
    }
    printf("%lld\n", ans);
}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111];
map<pair<ll,ll>,set<ll>> mp;
void solve()
{
    ll n; scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", x+i, y+i);
    forn(i, n) forn(j, i)
    {
        ll dy =y[i]-y[j], dx=x[i]-x[j];
        ll g = gcd(dy, dx);
        ll mx = dx/g, my = dy/g;
        mp[{mx, my}].insert(x[i]*my - y[i]*mx);
    }
    ll run = 0, ans = 0;
    for(auto line: mp)
    {
        ans += (ll) line.second.size()*run;
        run += line.second.size();
    }
    printf("%lld\n", ans);

}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111], n;
map<pair<ll,ll>, set<ll>> line;
void solve()
{
    scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", &x[i], &y[i]);
    forn(i, n) forn(j, i)
    {
        ll dx = x[i] - x[j];
        ll dy = y[i] - y[j];
        ll g = gcd(dx, dy);
        dx /=g;
        dy /=g;
        ll s = dy*x[i] - dx * y[i];
        line[{dx, dy}].insert(s);
    }
    ll r = 0;
    ll ans = 0;
    for(auto it : line)
    {
        ans += it.second.size()*r;
        r += it.second.size();
    }
    printf("%lld\n", ans);
}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111], n;
map<pair<ll,ll>, set<ll>> line;
void solve()
{
    scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", &x[i], &y[i]);
    forn(i, n) forn(j, i)
    {
        ll dx = x[i] - x[j];
        ll dy = y[i] - y[j];
        ll g = gcd(dx, dy);
        dx /=g;
        dy /=g;
        ll s = dx*dy*x[i] - dx*dx * y[i];
        line[{dx, dy}].insert(s);
    }
    ll r = 0;
    ll ans = 0;
    for(auto it : line)
    {
        ans += it.second.size()*r;
        r += it.second.size();
    }
    printf("%lld\n", ans);
}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111], n;
map<pair<ll,ll>, set<ll>> line;
void solve()
{
    scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", &x[i], &y[i]);
    forn(i, n) forn(j, i)
    {
        ll dx = x[i] - x[j];
        ll dy = y[i] - y[j];
        ll g = gcd(dx, dy);
        dx /=g;
        dy /=g;
        ll s = abs(dy*x[i] - dx * y[i]);
        line[{dx, dy}].insert(s);
    }
    ll r = 0;
    ll ans = 0;
    for(auto it : line)
    {
        ans += it.second.size()*r;
        r += it.second.size();
    }
    printf("%lld\n", ans);
}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111], n;
map<pair<ll,ll>, set<ll>> line;
void solve()
{
    scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", &x[i], &y[i]);
    for(int i=0;i<n;++i) for(int j=i+1;j<n;++j)
    {
        ll dx = x[i] - x[j];
        ll dy = y[i] - y[j];
        ll g = gcd(dy, dx);
        dx /=g;
        dy /=g;
        ll s = dy*x[i] - dx * y[i];
        line[{dy, dx}].insert(s);
    }
    ll r = 0;
    ll ans = 0;
    for(auto it : line)
    {
        ans += 1LL*it.second.size()*r;
        r += 1LL*it.second.size();
    }
    printf("%lld\n", ans);
}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111], n;
map<pair<ll,ll>, set<ll>> line;
void solve()
{
    scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", &x[i], &y[i]);
    for(int i=0;i<n;++i) for(int j=i+1;j<n;++j)
    {
        ll dx = x[i] - x[j];
        ll dy = y[i] - y[j];
        ll g = gcd(dx, dy);
        dx /=g;
        dy /=g;
        ll s = dy*x[i] - dx * y[i];
        line[{dy, dx}].insert(s);
    }
    ll r = 0;
    ll ans = 0;
    for(auto it : line)
    {
        ans += 1LL*it.second.size()*r;
        r += 1LL*it.second.size();
    }
    printf("%lld\n", ans);
}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111], n;
map<pair<ll,ll>, set<double>> line;
void solve()
{
    scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", &x[i], &y[i]);
    forn(i, n) forn(j, i)
    {
        ll dx = x[i] - x[j];
        ll dy = y[i] - y[j];
        ll g = gcd(dx, dy);
        dx /=g;
        dy /=g;
        double s;
        if (dy == 0) s = INT_MAX;
        else s = 1.0d*x[i] - 1.0d*dx/dy*y[i];
        line[{dx, dy}].insert(s);
    }
    ll r = 0;
    ll ans = 0;
    for(auto it : line)
    {
        ans += it.second.size()*r;
        r += it.second.size();
    }
    printf("%lld\n", ans);
}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111], n;
map<pair<ll,ll>, set<pair<double,double>>> line;
void solve()
{
    scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", &x[i], &y[i]);
    forn(i, n) forn(j, i)
    {
        ll dx = x[i] - x[j];
        ll dy = y[i] - y[j];
        ll g = gcd(dx, dy);
        dx /=g;
        dy /=g;
        double s;
        if (dy == 0) s = INT_MAX;
        else s = 1.0d*x[i] - 1.0d*dx/dy*y[i];
        double f;
        if(dx==0) f = INT_MAX;
        else f = 1.0d*y[i] - 1.0d*dy/dx*x[i];
        line[{dx, dy}].insert({f, s});
    }
    ll r = 0;
    ll ans = 0;
    for(auto it : line)
    {
        ans += 1LL*it.second.size()*r;
        r += 1LL*it.second.size();
    }
    printf("%lld\n", ans);
}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111], n;
map<pair<ll,ll>, set<pair<double,double>>> line;
void solve()
{
    scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", &x[i], &y[i]);
    forn(i, n) forn(j, i)
    {
        ll dx = x[i] - x[j];
        ll dy = y[i] - y[j];
        ll g = gcd(dx, dy);
        dx /=g;
        dy /=g;
        double s;
        if (dy == 0) s = INT_MAX;
        else s = 1.0d*x[i] - 1.0d*dx/dy*y[i];
        double f;
        if(dx==0) f = INT_MAX;
        else f = 1.0d*y[i] - 1.0d*dy/dx*x[i];
        line[{dx, dy}].insert({f, s});
    }
    ll r = 0;
    ll ans = 0;
    for(auto it : line)
    {
        ans += it.second.size()*r;
        r += it.second.size();
    }
    printf("%lld\n", ans);
}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111], n;
map<pair<ll,ll>, set<ll>> line;
void solve()
{
    scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", &x[i], &y[i]);
    forn(i, n) forn(j, i)
    {
        ll dx = x[i] - x[j];
        ll dy = y[i] - y[j];
        ll g = __gcd(dx, dy);
        dx /=g;
        dy /=g;
        ll s = dy*x[i] - dx * y[i];
        line[{dx, dy}].insert(s);
    }
    ll r = 0;
    ll ans = 0;
    for(auto it : line)
    {
        ans += it.second.size()*r;
        r += it.second.size();
    }
    printf("%lld\n", ans);
}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111], n;
map<pair<ll,ll>, set<pair<double,double>>> line;
void solve()
{
    scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", &x[i], &y[i]);
    forn(i, n) forn(j, i)
    {
        ll dx = x[i] - x[j];
        ll dy = y[i] - y[j];
        ll g = __gcd(dx, dy);
        dx /=g;
        dy /=g;
        double s;
        if (dy == 0) s = INT_MAX;
        else s = 1.0d*x[i] - 1.0d*dx/dy*y[i];
        double f;
        if(dx==0) f = INT_MAX;
        else f = 1.0d*y[i] - 1.0d*dy/dx*x[i];
        line[{dx, dy}].insert({f, s});
    }
    ll r = 0;
    ll ans = 0;
    for(auto it : line)
    {
        ans += it.second.size()*r;
        r += it.second.size();
    }
    printf("%lld\n", ans);
}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i, n) for(int i = 0; i<int(n);++i)
ll x[1111], y[1111], n;
map<pair<ll,ll>, set<ll>> line;
void solve()
{
    scanf("%lld", &n);
    forn(i, n) scanf("%lld%lld", &x[i], &y[i]);
    for(int i=0;i<n;++i) for(int j=i+1;j<n;++j)
    {
        ll dx = x[i] - x[j];
        ll dy = y[i] - y[j];
        ll g = gcd(dx, dy);
        dx /=g;
        dy /=g;
        ll s = dy*x[i] - dx * y[i];
        line[{dx, dy}].insert(s);
    }
    ll r = 0;
    ll ans = 0;
    for(auto it : line)
    {
        ans += 1LL*it.second.size()*r;
        r += 1LL*it.second.size();
    }
    printf("%lld\n", ans);
}

int main()
{
    int T = 1;
    while(T--) solve();
	return 0;
}


#include <bits/stdc++.h>
#define FASTIO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
#define LL long long int
const int N = 3e5 + 5;
const int M = 5e5 + 5;
const int MOD = 1e9 + 7;

int x[N], y[N];
int main() {
  FASTIO;
  int n, i, j;
  cin >> n;
  for (i=0;i<n;i++) {
    cin >> x[i] >> y[i];
  }
  map<pair<LL, LL>, vector<LL>> mp;
  for (i=0;i<n;i++) {
    for (j=i+1;j<n;j++) {
      LL a = (x[j] - x[i]), b = -(y[j] - y[i]);
      LL sgn = 1;
      if (a < 0) sgn = -1;
      else if (a == 0 && b < 0) sgn = -1;
      LL g = __gcd(abs(a), abs(b));
      LL c = y[i] * (x[j] - x[i]) - x[i] * (y[j] - y[i]);
      a /= g;b /= g;c /= g;
      a *= sgn; b *= sgn; c *= sgn;
      mp[{a, b}].push_back(c);
    }
  }
  LL sum = 0, sumsq = 0;
  for (auto it : mp) {
    // cout << it.first.first << " " << it.first.second << " " << it.second << '\n';
    vector<LL> now = it.second;
    sort(now.begin(), now.end());
    now.erase(unique(now.begin(), now.end()), now.end());
    LL sz = now.size();
    sum += sz;
    sumsq += sz * sz;
  }
  cout << (sum * sum - sumsq)/2 << '\n';

  return 0;
}


#include <bits/stdc++.h>
#define FASTIO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
#define LL long long int
const int N = 3e5 + 5;
const int M = 5e5 + 5;
const int MOD = 1e9 + 7;

int x[N], y[N];
int main() {
  FASTIO;
  int n, i, j;
  cin >> n;
  for (i=0;i<n;i++) {
    cin >> x[i] >> y[i];
  }
  map<pair<LL, LL>, vector<pair<LL, LL>>> mp;
  for (i=0;i<n;i++) {
    for (j=i+1;j<n;j++) {
      LL a = (x[j] - x[i]), b = -(y[j] - y[i]);
      LL sgn = 1;
      if (a < 0) sgn *= -1;
      LL g = __gcd(abs(a), abs(b));
      a /= g;
      b /= g;
      LL c = y[i] * (x[j] - x[i]) - x[i] * (y[j] - y[i]);
      c *= sgn;a *= sgn; b *= sgn;
      LL go = __gcd(g, abs(c));
      mp[make_pair(a, b)].push_back({c/go, g/go});
    }
  }
  LL sum = 0, sumsq = 0;
  for (auto it : mp) {
    // cout << it.first.first << " " << it.first.second << " " << it.second << '\n';
    vector<pair<LL, LL>> now = it.second;
    sort(now.begin(), now.end());
    now.erase(unique(now.begin(), now.end()), now.end());
    LL sz = now.size();
    sum += sz;
    sumsq += sz * sz;
  }
  cout << (sum * sum - sumsq)/2 << '\n';

  return 0;
}


#include <bits/stdc++.h>
#define FASTIO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
#define LL long long int
const int N = 3e5 + 5;
const int M = 5e5 + 5;
const int MOD = 1e9 + 7;

int x[N], y[N];
int main() {
  FASTIO;
  int n, i, j;
  cin >> n;
  for (i=0;i<n;i++) {
    cin >> x[i] >> y[i];
  }
  map<pair<LL, LL>, vector<LL>> mp;
  for (i=0;i<n;i++) {
    for (j=i+1;j<n;j++) {
      LL a = (x[i] - x[j]), b = -(y[i] - y[j]);
      if (a < 0) {
        a *= -1;
        b *= -1;
      }
      LL g = __gcd(a, b);
      a /= g;
      b /= g;
      LL c = y[i] * (x[j] - x[i]) - x[i] * (y[j] - y[i]);
      c /= g;
      mp[make_pair(a, b)].push_back(c);
    }
  }
  LL sum = 0, sumsq = 0;
  for (auto it : mp) {
    // cout << it.first.first << " " << it.first.second << " " << it.second << '\n';
    vector<LL> now = it.second;
    sort(now.begin(), now.end());
    now.erase(unique(now.begin(), now.end()), now.end());
    LL sz = now.size();
    sum += sz;
    sumsq += sz * sz;
  }
  cout << (sum * sum - sumsq)/2 << '\n';

  return 0;
}


#include <bits/stdc++.h>
#define FASTIO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
#define LL long long int
const int N = 3e5 + 5;
const int M = 5e5 + 5;
const int MOD = 1e9 + 7;

int x[N], y[N];
int main() {
  FASTIO;
  int n, i, j;
  cin >> n;
  for (i=0;i<n;i++) {
    cin >> x[i] >> y[i];
  }
  map<pair<int, int>, vector<LL>> mp;
  for (i=0;i<n;i++) {
    for (j=i+1;j<n;j++) {
      int a = (x[i] - x[j]), b = -(y[i] - y[j]);
      if (a < 0) {
        a *= -1;
        b *= -1;
      }
      int g = __gcd(a, b);
      a /= g;
      b /= g;
      LL c = y[i] * (x[j] - x[i]) - x[i] * (y[j] - y[i]);
      mp[make_pair(a, b)].push_back(c);
    }
  }
  LL sum = 0, sumsq = 0;
  for (auto it : mp) {
    // cout << it.first.first << " " << it.first.second << " " << it.second << '\n';
    vector<LL> now = it.second;
    sort(now.begin(), now.end());
    now.erase(unique(now.begin(), now.end()), now.end());
    LL sz = now.size();
    sum += sz;
    sumsq += sz * sz;
  }
  cout << (sum * sum - sumsq)/2 << '\n';

  return 0;
}


#include <bits/stdc++.h>
#define FASTIO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
#define LL long long int
const int N = 3e5 + 5;
const int M = 5e5 + 5;
const int MOD = 1e9 + 7;

int x[N], y[N];
int main() {
  FASTIO;
  int n, i, j;
  cin >> n;
  for (i=0;i<n;i++) {
    cin >> x[i] >> y[i];
  }
  map<pair<LL, LL>, vector<pair<LL, LL>>> mp;
  for (i=0;i<n;i++) {
    for (j=i+1;j<n;j++) {
      LL a = (x[j] - x[i]), b = -(y[j] - y[i]);
      if (a < 0) {
        a *= -1;
        b *= -1;
      }
      LL g = __gcd(a, abs(b));
      a /= g;
      b /= g;
      LL c = y[i] * (x[j] - x[i]) - x[i] * (y[j] - y[i]);
      LL go = __gcd(g, abs(c));
      mp[make_pair(a, b)].push_back({c/go, g/go});
    }
  }
  LL sum = 0, sumsq = 0;
  for (auto it : mp) {
    // cout << it.first.first << " " << it.first.second << " " << it.second << '\n';
    vector<pair<LL, LL>> now = it.second;
    sort(now.begin(), now.end());
    now.erase(unique(now.begin(), now.end()), now.end());
    LL sz = now.size();
    sum += sz;
    sumsq += sz * sz;
  }
  cout << (sum * sum - sumsq)/2 << '\n';

  return 0;
}


#include <bits/stdc++.h>

#define pb push_back

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ll INF = (ll)1<<62;
const ll MOD = 1e9+7;

ll gcd(ll a, ll b){
	if(b==0)
		return a;
	else
		return gcd(b, a%b);
}

int main(){
	ll n;
	vector<pair<int, int> > pts;
	set<tuple<ll, ll, ll> > lines;
	vector<tuple<ll, ll, ll> > linev;

	cin>>n;
	for(int i=0;i<n;i++){
		ll x, y;
		cin>>x>>y;
		pts.pb({x, y});
	}

	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			ll x1 = pts[i].first;
			ll x2 = pts[j].first;
			ll y1 = pts[i].second;
			ll y2 = pts[j].second;

			ll g = gcd(x2-x1, gcd(y1-y2, y2*x1-x2*y1));
			if(g<0)
				g*=-1;

			tuple<ll, ll, ll> curr((x2-x1)/g, (y1-y2)/g, (y2*x1-x2*y1)/g);
			if(lines.count(curr) == 0){
				lines.insert(curr);
				linev.pb(curr);
			}
		}
	}

	map<pair<ll, ll>, ll> slopes;
	for(int i=0;i<linev.size();i++){
		ll num = -get<1>(linev[i]);
		ll den = get<0>(linev[i]);
		if(den == 0){
			pair<ll, ll> curr(0, 0);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else if(n==0){
			pair<ll, ll> curr(0, INF);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else{
			pair<ll, ll> curr(num, den);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
	}

	ll nx = lines.size();
	ll ans = (nx*(nx-1))/2;
	for(auto it=slopes.begin(); it!=slopes.end(); it++){
		ll tmp = it->second;
		ans -= (tmp*(tmp-1))/2;
	}

	cout<<ans<<"\n";

	return 0;
}


#include <bits/stdc++.h>

#define pb push_back

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ll INF = (ll)1<<62;
const ll MOD = 1e9+7;

ll gcd(ll a, ll b){
	if(b==0)
		return a;
	else
		return gcd(b, a%b);
}

int main(){
	ll n;
	vector<pair<int, int> > pts;
	set<tuple<ll, ll, ll> > lines;
	vector<tuple<ll, ll, ll> > linev;

	cin>>n;
	for(int i=0;i<n;i++){
		ll x, y;
		cin>>x>>y;
		pts.pb({x, y});
	}

	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			ll x1 = pts[i].first;
			ll x2 = pts[j].first;
			ll y1 = pts[i].second;
			ll y2 = pts[j].second;

			ll g = gcd(y1-y2, gcd(x2-x1, y2*x1-x2*y1));
			if(g<0)
				g*=-1;

			ll a = (y1-y2)/g;
			ll b = (x2-x1)/g;
			ll c = (y2*x1-x2*y1)/g;

			if(a<=0 && b<=0){
				a*=-1;b*=-1;c*=-1;
			}

			//cout<<i<<" "<<j<<" "<<g<<" "<<(y1-y2)/g<<" "<<(x2-x1)/g<<" "<<(y2*x1-x2*y1)/g<<"\n";

			tuple<ll, ll, ll> curr(a, b, c);
			if(lines.count(curr) == 0){
				lines.insert(curr);
				linev.pb(curr);
			}
		}
	}

	ll ans = 0;
	for(int i=0;i<linev.size();i++){
		ll a1 = get<0>(linev[i]);
		ll b1 = get<1>(linev[i]);
		for(int j=i+1;j<linev.size();j++){
			ll a2 = get<0>(linev[j]);
			ll b2 = get<1>(linev[j]);

			if(b1*a2 != b2*a1){
				if(a1 == 0 && a2 == 0)
					continue;
				else if(b1 == 0 && b2 == 0)
					continue;
				ans++;
			}
		}
	}

	cout<<ans<<"\n";

	return 0;
}


#include <bits/stdc++.h>

#define pb push_back

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ll INF = (ll)1<<62;
const ll MOD = 1e9+7;

ll gcd(ll a, ll b){
	if(b==0)
		return a;
	else
		return gcd(b, a%b);
}

int main(){
	ll n;
	vector<pair<ll, ll> > pts;
	set<tuple<ll, ll, ll> > lines;
	vector<tuple<ll, ll, ll> > linev;

	cin>>n;
	for(int i=0;i<n;i++){
		ll x, y;
		cin>>x>>y;
		pts.pb({x, y});
	}

	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			ll x1 = pts[i].first;
			ll x2 = pts[j].first;
			ll y1 = pts[i].second;
			ll y2 = pts[j].second;

			ll g = gcd(y1-y2, gcd(x2-x1, y2*x1-x2*y1));
			if(g<0)
				g*=-1;

			ll a = (y1-y2)/g;
			ll b = (x2-x1)/g;
			ll c = (y2*x1-x2*y1)/g;

			if(a<0){
				a*=-1;b*=-1;c*=-1;
			}
			else if(a==0){
				if(b<0){
					b*=-1;c*=-1;
				}
			}

			//cout<<i<<" "<<j<<" "<<g<<" "<<(y1-y2)/g<<" "<<(x2-x1)/g<<" "<<(y2*x1-x2*y1)/g<<"\n";

			tuple<ll, ll, ll> curr(a, b, c);
			if(lines.count(curr) == 0){
				lines.insert(curr);
				linev.pb(curr);
			}
		}
	}

	map<pair<ll, ll>, ll> slopes;
	for(int i=0;i<linev.size();i++){
		ll num = get<0>(linev[i]);
		ll den = get<1>(linev[i]);
		if(den == 0){
			pair<ll, ll> curr(INF, 0);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else if(num == 0){
			pair<ll, ll> curr(0, INF);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else{
			pair<ll, ll> curr(num, den);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
	}

	ll nx = linev.size();
	ll ans = (nx*(nx-1))/2;
	for(auto it=slopes.begin(); it!=slopes.end(); it++){
		ll tmp = it->second;
		ans -= (tmp*(tmp-1))/2;
	}

	cout<<ans<<"\n";

	return 0;
}


#include <bits/stdc++.h>

#define pb push_back

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ll INF = (ll)1<<62;
const ll MOD = 1e9+7;

ll gcd(ll a, ll b){
	if(b==0)
		return a;
	else
		return gcd(b, a%b);
}

int main(){
	ll n;
	vector<pair<int, int> > pts;
	set<tuple<ll, ll, ll> > lines;
	vector<tuple<ll, ll, ll> > linev;

	cin>>n;
	for(int i=0;i<n;i++){
		ll x, y;
		cin>>x>>y;
		pts.pb({x, y});
	}

	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			ll x1 = pts[i].first;
			ll x2 = pts[j].first;
			ll y1 = pts[i].second;
			ll y2 = pts[j].second;

			ll g = gcd(x2-x1, gcd(y1-y2, y2*x1-x2*y1));
			if(g<0)
				g*=-1;

			tuple<ll, ll, ll> curr((x2-x1)/g, (y1-y2)/g, (y2*x1-x2*y1)/g);
			if(lines.count(curr) == 0){
				lines.insert(curr);
				linev.pb(curr);
			}
		}
	}

	map<pair<ll, ll>, ll> slopes;
	for(int i=0;i<linev.size();i++){
		ll num = -get<1>(linev[i]);
		ll den = get<0>(linev[i]);
		if(den == 0){
			pair<ll, ll> curr(0, 0);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else if(num==0){
			pair<ll, ll> curr(0, INF);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else{
			pair<ll, ll> curr(num, den);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
	}

	ll nx = lines.size();
	ll ans = (nx*(nx-1))/2;
	for(auto it=slopes.begin(); it!=slopes.end(); it++){
		ll tmp = it->second;
		ans -= (tmp*(tmp-1))/2;
	}

	cout<<ans<<"\n";

	return 0;
}


#include <bits/stdc++.h>

#define pb push_back

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ll INF = (ll)1<<62;
const ll MOD = 1e9+7;

ll gcd(ll a, ll b){
	if(b==0)
		return a;
	else
		return gcd(b, a%b);
}

int main(){
	ll n;
	vector<pair<int, int> > pts;
	set<tuple<ll, ll, ll> > lines;
	vector<tuple<ll, ll, ll> > linev;

	cin>>n;
	for(int i=0;i<n;i++){
		ll x, y;
		cin>>x>>y;
		pts.pb({x, y});
	}

	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			ll x1 = pts[i].first;
			ll x2 = pts[j].first;
			ll y1 = pts[i].second;
			ll y2 = pts[j].second;

			ll g = gcd(y1-y2, gcd(x2-x1, y2*x1-x2*y1));
			if(g<0)
				g*=-1;

			ll a = (y1-y2)/g;
			ll b = (x2-x1)/g;
			ll c = (y2*x1-x2*y1)/g;

			if(a<=0){
				a*=-1;b*=-1;c*=-1;
			}

			//cout<<i<<" "<<j<<" "<<g<<" "<<(y1-y2)/g<<" "<<(x2-x1)/g<<" "<<(y2*x1-x2*y1)/g<<"\n";

			tuple<ll, ll, ll> curr(a, b, c);
			if(lines.count(curr) == 0){
				lines.insert(curr);
				linev.pb(curr);
			}
		}
	}

	ll ans = 0;
	for(int i=0;i<linev.size();i++){
		ll a1 = get<0>(linev[i]);
		ll b1 = get<1>(linev[i]);
		for(int j=i+1;j<linev.size();j++){
			ll a2 = get<0>(linev[j]);
			ll b2 = get<1>(linev[j]);

			if(b1*a2 != b2*a1){
				if(a1 == 0 && a2 == 0)
					continue;
				else if(b1 == 0 && b2 == 0)
					continue;
				ans++;
			}
		}
	}

	cout<<ans<<"\n";

	return 0;
}


#include <bits/stdc++.h>

#define pb push_back

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ll INF = (ll)1<<62;
const ll MOD = 1e9+7;

ll gcd(ll a, ll b){
	if(b==0)
		return a;
	else
		return gcd(b, a%b);
}

int main(){
	ll n;
	vector<pair<int, int> > pts;
	set<tuple<ll, ll, ll> > lines;
	vector<tuple<ll, ll, ll> > linev;

	cin>>n;
	for(int i=0;i<n;i++){
		ll x, y;
		cin>>x>>y;
		pts.pb({x, y});
	}

	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			ll x1 = pts[i].first;
			ll x2 = pts[j].first;
			ll y1 = pts[i].second;
			ll y2 = pts[j].second;

			ll g = gcd(y1-y2, gcd(x2-x1, y2*x1-x2*y1));
			if(g<0)
				g*=-1;

			//cout<<i<<" "<<j<<" "<<g<<" "<<(y1-y2)/g<<" "<<(x2-x1)/g<<" "<<(y2*x1-x2*y1)/g<<"\n";

			tuple<ll, ll, ll> curr((y1-y2)/g, (x2-x1)/g, (y2*x1-x2*y1)/g);
			if(lines.count(curr) == 0){
				lines.insert(curr);
				linev.pb(curr);
			}
		}
	}

	ll ans = 0;
	for(int i=0;i<linev.size();i++){
		ll a1 = get<0>(linev[i]);
		ll b1 = get<1>(linev[i]);
		for(int j=i+1;j<linev.size();j++){
			ll a2 = get<0>(linev[j]);
			ll b2 = get<1>(linev[j]);

			if(b1*a2 != b2*a1){
				if(a1 == 0 && a2 == 0)
					continue;
				else if(b1 == 0 && b2 == 0)
					continue;
				ans++;
			}
		}
	}

	cout<<ans<<"\n";

	return 0;
}


#include <bits/stdc++.h>

#define pb push_back

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ll INF = (ll)1<<62;
const ll MOD = 1e9+7;

ll gcd(ll a, ll b){
	if(b==0)
		return a;
	else
		return gcd(b, a%b);
}

int main(){
	ll n;
	vector<pair<int, int> > pts;
	set<tuple<ll, ll, ll> > lines;
	vector<tuple<ll, ll, ll> > linev;

	cin>>n;
	for(int i=0;i<n;i++){
		ll x, y;
		cin>>x>>y;
		pts.pb({x, y});
	}

	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			ll x1 = pts[i].first;
			ll x2 = pts[j].first;
			ll y1 = pts[i].second;
			ll y2 = pts[j].second;

			ll g = gcd(y1-y2, gcd(x2-x1, y2*x1-x2*y1));
			if(g<0)
				g*=-1;

			ll a = (y1-y2)/g;
			ll b = (x2-x1)/g;
			ll c = (y2*x1-x2*y1)/g;

			if(a<=0){
				a*=-1;b*=-1;c*=-1;
			}

			//cout<<i<<" "<<j<<" "<<g<<" "<<(y1-y2)/g<<" "<<(x2-x1)/g<<" "<<(y2*x1-x2*y1)/g<<"\n";

			tuple<ll, ll, ll> curr(a, b, c);
			if(lines.count(curr) == 0){
				lines.insert(curr);
				linev.pb(curr);
			}
		}
	}

	map<pair<ll, ll>, ll> slopes;
	for(int i=0;i<linev.size();i++){
		ll num = -get<0>(linev[i]);
		ll den = get<1>(linev[i]);
		if(den == 0){
			pair<ll, ll> curr(0, 0);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else if(num == 0){
			pair<ll, ll> curr(0, INF);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else{
			pair<ll, ll> curr(num, den);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
	}

	ll nx = lines.size();
	ll ans = (nx*(nx-1))/2;
	for(auto it=slopes.begin(); it!=slopes.end(); it++){
		ll tmp = it->second;
		ans -= (tmp*(tmp-1))/2;
	}

	cout<<ans<<"\n";

	return 0;
}


#include <bits/stdc++.h>

#define pb push_back

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ll INF = (ll)1<<62;
const ll MOD = 1e9+7;

ll gcd(ll a, ll b){
	if(b==0)
		return a;
	else
		return gcd(b, a%b);
}

int main(){
	ll n;
	vector<pair<int, int> > pts;
	set<tuple<ll, ll, ll> > lines;
	vector<tuple<ll, ll, ll> > linev;

	cin>>n;
	for(int i=0;i<n;i++){
		ll x, y;
		cin>>x>>y;
		pts.pb({x, y});
	}

	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			ll x1 = pts[i].first;
			ll x2 = pts[j].first;
			ll y1 = pts[i].second;
			ll y2 = pts[j].second;

			ll g = gcd(y1-y2, gcd(x2-x1, y2*x1-x2*y1));
			if(g<0)
				g*=-1;

			tuple<ll, ll, ll> curr((y1-y2)/g, (x2-x1)/g, (y2*x1-x2*y1)/g);
			if(lines.count(curr) == 0){
				lines.insert(curr);
				linev.pb(curr);
			}
		}
	}

	map<pair<ll, ll>, ll> slopes;
	for(int i=0;i<linev.size();i++){
		ll num = -get<1>(linev[i]);
		ll den = get<0>(linev[i]);
		if(den == 0){
			pair<ll, ll> curr(0, 0);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else if(num==0){
			pair<ll, ll> curr(0, INF);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else{
			pair<ll, ll> curr(num, den);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
	}

	ll nx = lines.size();
	ll ans = (nx*(nx-1))/2;
	for(auto it=slopes.begin(); it!=slopes.end(); it++){
		ll tmp = it->second;
		ans -= (tmp*(tmp-1))/2;
	}

	cout<<ans<<"\n";

	return 0;
}


#include <bits/stdc++.h>

#define pb push_back

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ll INF = (ll)1<<62;
const ll MOD = 1e9+7;

ll gcd(ll a, ll b){
	if(b==0)
		return a;
	else
		return gcd(b, a%b);
}

int main(){
	ll n;
	vector<pair<ll, ll> > pts;
	set<tuple<ll, ll, ll> > lines;
	vector<tuple<ll, ll, ll> > linev;

	cin>>n;
	for(int i=0;i<n;i++){
		ll x, y;
		cin>>x>>y;
		pts.pb({x, y});
	}

	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			ll x1 = pts[i].first;
			ll x2 = pts[j].first;
			ll y1 = pts[i].second;
			ll y2 = pts[j].second;

			ll g = gcd(y1-y2, gcd(x2-x1, y2*x1-x2*y1));
			if(g<0)
				g*=-1;

			ll a = (y1-y2)/g;
			ll b = (x2-x1)/g;
			ll c = (y2*x1-x2*y1)/g;

			if(a<0){
				a*=-1;b*=-1;c*=-1;
			}
			else if(a==0){
				if(b<0)
					b*=-1;c*=-1;
			}

			//cout<<i<<" "<<j<<" "<<g<<" "<<(y1-y2)/g<<" "<<(x2-x1)/g<<" "<<(y2*x1-x2*y1)/g<<"\n";

			tuple<ll, ll, ll> curr(a, b, c);
			if(lines.count(curr) == 0){
				lines.insert(curr);
				linev.pb(curr);
			}
		}
	}

	map<pair<ll, ll>, ll> slopes;
	for(int i=0;i<linev.size();i++){
		ll num = get<0>(linev[i]);
		ll den = get<1>(linev[i]);
		if(den == 0){
			pair<ll, ll> curr(INF, 0);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else if(num == 0){
			pair<ll, ll> curr(0, INF);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else{
			pair<ll, ll> curr(num, den);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
	}

	ll nx = linev.size();
	ll ans = (nx*(nx-1))/2;
	for(auto it=slopes.begin(); it!=slopes.end(); it++){
		ll tmp = it->second;
		ans -= (tmp*(tmp-1))/2;
	}

	cout<<ans<<"\n";

	return 0;
}


#include <bits/stdc++.h>

#define pb push_back

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ll INF = (ll)1<<62;
const ll MOD = 1e9+7;

ll gcd(ll a, ll b){
	if(b==0)
		return a;
	else
		return gcd(b, a%b);
}

int main(){
	ll n;
	vector<pair<int, int> > pts;
	set<tuple<ll, ll, ll> > lines;
	vector<tuple<ll, ll, ll> > linev;

	cin>>n;
	for(int i=0;i<n;i++){
		ll x, y;
		cin>>x>>y;
		pts.pb({x, y});
	}

	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			ll x1 = pts[i].first;
			ll x2 = pts[j].first;
			ll y1 = pts[i].second;
			ll y2 = pts[j].second;

			ll g = gcd(x2-x1, gcd(y1-y2, y2*x1-x2*y1));
			if(g<0)
				g*=-1;

			tuple<ll, ll, ll> curr((x2-x1)/g, (y1-y2)/g, (y2*x1-x2*y1)/g);
			if(lines.count(curr) == 0){
				lines.insert(curr);
				linev.pb(curr);
			}
		}
	}

	map<pair<ll, ll>, ll> slopes;
	for(int i=0;i<linev.size();i++){
		ll num = -get<1>(linev[i]);
		ll den = get<0>(linev[i]);
		if(den == 0){
			pair<ll, ll> curr(0, 0);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
		else{
			pair<ll, ll> curr(num, den);
			if(slopes.count(curr) == 0)
				slopes[curr] = 1;
			else
				slopes[curr]++;
		}
	}

	ll nx = lines.size();
	ll ans = (nx*(nx-1))/2;
	for(auto it=slopes.begin(); it!=slopes.end(); it++){
		ll tmp = it->second;
		ans -= (tmp*(tmp-1))/2;
	}

	cout<<ans<<"\n";

	return 0;
}


#include <bits/stdc++.h>

#define pb push_back

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ll INF = (ll)1<<62;
const ll MOD = 1e9+7;

ll gcd(ll a, ll b){
	if(b==0)
		return a;
	else
		return gcd(b, a%b);
}

int main(){
	ll n;
	vector<pair<int, int> > pts;
	set<tuple<ll, ll, ll> > lines;
	vector<tuple<ll, ll, ll> > linev;

	cin>>n;
	for(int i=0;i<n;i++){
		ll x, y;
		cin>>x>>y;
		pts.pb({x, y});
	}

	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			ll x1 = pts[i].first;
			ll x2 = pts[j].first;
			ll y1 = pts[i].second;
			ll y2 = pts[j].second;

			ll g = gcd(y1-y2, gcd(x2-x1, y2*x1-x2*y1));
			if(g<0)
				g*=-1;

			tuple<ll, ll, ll> curr((y1-y2)/g, (x2-x1)/g, (y2*x1-x2*y1)/g);
			if(lines.count(curr) == 0){
				lines.insert(curr);
				linev.pb(curr);
			}
		}
	}

	ll ans = 0;
	for(int i=0;i<linev.size();i++){
		ll a1 = get<0>(linev[i]);
		ll b1 = get<1>(linev[i]);
		for(int j=i+1;j<linev.size();j++){
			ll a2 = get<0>(linev[j]);
			ll b2 = get<1>(linev[j]);

			if(b1*a2 != b2*a1)
				ans++;
		}
	}

	cout<<ans<<"\n";

	return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define sync_cin                      \
    ios_base::sync_with_stdio(false); \
    cin.tie(0)
#define sz(a) (int)a.size()

using namespace std;

#define TYPEMAX(type)   std::numeric_limits<type>::max()
#define TYPEMIN(type)   std::numeric_limits<type>::min()
const int MOD = 1e9 + 7;
const int N = 2e5 + 5;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> ii;

int main()
{
    sync_cin;
    int n; cin >> n;
    vector<ii> p(n);
    for (int i = 0; i < n; i++)
    {
        int x, y; cin >> x >> y;
        p[i] = {x, y};
    }

    map<ii, int> K;
    set<int> H, V;
    for (int i = 0; i < n; i++)
        for (int j = i + 1; j < n; j++)
        {
            int dif_y = p[j].second - p[i].second;
            int dif_x = p[j].first - p[i].first;
            if (dif_x == 0) V.insert(p[j].first);
            else if (dif_y == 0) H.insert(p[j].second);
            else {
                int g = __gcd(dif_y, dif_x);
                dif_y /= g;
                dif_x /= g;
                K[{dif_y, dif_x}]++;
            }
        }

    ll h = H.size();
    ll v = V.size();
    ll k = K.size();

    ll ans = 1ll * h * v + 1ll * (h + v) * k + 1ll * k * (k - 1) / 2;
    cout << ans << endl;
    return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define sync_cin                      \
    ios_base::sync_with_stdio(false); \
    cin.tie(0)
#define sz(a) (int)a.size()

using namespace std;

#define TYPEMAX(type)   std::numeric_limits<type>::max()
#define TYPEMIN(type)   std::numeric_limits<type>::min()
const int MOD = 1e9 + 7;
const int N = 2e5 + 5;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> ii;

int main()
{
    sync_cin;
    int n; cin >> n;
    vector<ii> p(n);
    for (int i = 0; i < n; i++)
    {
        int x, y; cin >> x >> y;
        p[i] = {x, y};
    }
    sort(p.begin(), p.end());
    map<pair<ii, int>, int> K;
    set<int> H, V;
    for (int i = 0; i < n; i++)
        for (int j = i + 1; j < n; j++)
        {
            int dif_y = p[j].second - p[i].second;
            int dif_x = p[j].first - p[i].first;
            if (dif_x == 0) V.insert(p[j].first);
            else if (dif_y == 0) H.insert(p[j].second);
            else {
                int g = __gcd(abs(dif_y), abs(dif_x));
                int sgn = (1ll * dif_y * dif_x > 0 ? 1 : -1);
                dif_y /= g;
                dif_x /= g;
                K[{{abs(dif_y), abs(dif_x)}, sgn}]++;
            }
        }

    ll h = (ll) H.size();
    ll v = (ll) V.size();
    ll k = (ll) K.size();

    ll ans = 1ll * h * v + 1ll * (h + v) * k + 1ll * k * (k - 1) / 2;

    cout << ans << endl;
    return 0;
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Numerics;

public class Example
{
    public struct Din
    {
        public int value;
        public int number;
    }

    public class DinComparer : IComparer<Din>
    {
        public int Compare(Din x, Din y)
        {
            // Compare y and x in reverse order.
            return x.value.CompareTo(y.value);
        }
    }

    public static void Main()
    {

        string[] smas;

        smas = Console.ReadLine().Split(' ');
        int n = int.Parse(smas[0]);
        int v = int.Parse(smas[1]);

        //Din[] mm = new Din[200001];
        int max_pos = 1;
        int max_i = 0;
        Din[] m1 = new Din[100001];
        Din[] m2 = new Din[100001];
        int c1 = 0;
        int c2 = 0;

        for (int i = 0; i< n; i++)
        {
            smas = Console.ReadLine().Split(' ');
            int t = int.Parse(smas[0]);
            int p = int.Parse(smas[1]);
            var din = new Din() { value = p, number = i+1};
            if (t == 1)
            {
                m1[c1] = din;
                c1 ++;
            } else
            {
                m2[c2] = din;
                c2 ++;
            }
        }
        Array.Sort(m1, 0, c1, new DinComparer());
        Array.Sort(m2, 0, c2, new DinComparer());

        List<Din> result = new List<Din>();

        int tek1 = c1-1;
        int tek2 = c2-1;

        while (v > 0)
        {
            bool f = false;
            if (v == 1)
            {
                if (tek1 >= 0)
                {
                    result.Add(m1[tek1]);
                    tek1--;
                    f = true;
                    v--;
                }
            }
            else
            {
                if (tek2 >= 0)
                {
                    if (tek1 >= 1)
                    {
                        if (m2[tek2].value > m1[tek1].value + m1[tek1 - 1].value)
                        {
                            result.Add(m2[tek2]);
                            tek2--;
                            f = true;
                            v -= 2;
                        }
                        else
                        {
                            result.Add(m1[tek1]);
                            result.Add(m1[tek1 - 1]);
                            tek1 -= 2;
                            f = true;
                            v -= 2;
                        }
                    }
                    else if (tek1 == 0)
                    {
                        if (m2[tek2].value > m1[tek1].value)
                        {
                            result.Add(m2[tek2]);
                            tek2--;
                            f = true;
                            v -= 2;
                        }
                        else
                        {
                            result.Add(m2[tek1]);
                            tek1 -= 1;
                            f = true;
                            v -= 1;
                        }
                    }
                }
                else
                {
                    if (tek1 >= 1)
                    {
                        result.Add(m2[tek1]);
                        result.Add(m2[tek1 - 1]);
                        tek1 -= 2;
                        f = true;
                        v -= 2;
                    }
                    else if (tek1 == 0)
                    {
                        result.Add(m2[tek1]);
                        tek1 -= 1;
                        f = true;
                        v -= 1;
                    }
                }

            }

            if (!f) break;
        }

        int s = 0;
        foreach (var d in result)
        {
            s += d.value;
        }

        Console.WriteLine(s);
        foreach (var d in result)
        {
            Console.WriteLine(d.number);
        }

            //Array.Sort(

            //for (int j = max_pos; j >= 0; j--)
            //{
            //    if (mm[j].value != 0 || j == 0)
            //    {
            //        int new_val = mm[j].value + p;
            //        if (mm[j + t].value < new_val)
            //        {
            //            mm[j + t].value = new_val;
            //            mm[j + t].last_number = i + 1;
            //            mm[j + t].last_jump = t;

            //            if (((j + t) <= v) && mm[max_i].value < mm[j + t].value) max_i = j + t;
            //        }
            //    }
            //}

            //max_pos += t;
        //}
        //Console.WriteLine(mm[max_i].value);
        //while (max_i > 0)
        //{
        //    Console.WriteLine(mm[max_i].last_number);
        //    max_i -= mm[max_i].last_jump;
        //}

    }
}