#include <bits/stdc++.h>   using namespace std;   const long double EPS = 1e-9;   const long double PI = 3.141592653589793238462643383279502884197;   const int MOD = 666013;   const int NMax = 350000;   int N, C, D;   int lastIndexForSearch;   long long ans = 0LL;   struct Punct;   long long diferente[NMax], diferentePartiale[NMax];   long long sqr(const long long &x);   long long Determinant(const Punct &A, const Punct &B, const Punct &C);   long long Dist2(const Punct &A, const Punct &B);   long double GetAngle(const Punct &A);   int GetCadran(const Punct &A);   long long CompareUnghiPolar(const Punct &A, const Punct &B);   struct Punct {     int x, y;     Punct() {       this->x = 0;       this->y = 0;     }     Punct(const int x, const int y) {       this->x = x;       this->y = y;     }     inline bool operator<(const Punct &other) const {       long long s = CompareUnghiPolar(*this, other);       if (s == 0) return Dist2(Punct(0, 0), *this) < Dist2(Punct(0, 0), other);       return s == -1;     }   };   Punct a[NMax];   enum InsertType {     InsertCoord,     InsertCntStrict,     InsertCntNestrict,     InsertIndexNestrict   };   enum QueryType {     QueryCoord,     QueryCntStrict,     QueryCntNestrict,     QueryIndexNestrict   };   struct HashNode {     int x, y, indexNestrict;     long long cntStrict, cntNestrict;     HashNode() {       x = y = indexNestrict = 0;       cntStrict = cntNestrict = 0LL;     }     HashNode(const int &x, const int &y, const int &indexNestrict,              const long long &cntStrict, const long long &cntNestrict) {       this->x = x;       this->y = y;       this->indexNestrict = indexNestrict;       this->cntStrict = cntStrict;       this->cntNestrict = cntNestrict;     }   };   vector<HashNode> H[MOD];   struct CntEvidence {     int x, y;     long long cnt;     CntEvidence() {       x = y = 0;       cnt = 0LL;     }     CntEvidence(const int &x, const int &y, const long long &cnt) {       this->x = x;       this->y = y;       this->cnt = cnt;     }     inline bool operator<(const CntEvidence &other) const {       long long s =           CompareUnghiPolar(Punct(this->x, this->y), Punct(other.x, other.y));       if (s == 0)         return Dist2(Punct(0, 0), Punct(this->x, this->y)) <                Dist2(Punct(0, 0), Punct(other.x, other.y));       return s == -1;     }   };   CntEvidence maiMiciStrictVector[NMax];   CntEvidence maiMiciStrictVectorSumePartiale[NMax];   CntEvidence maiMiciSauEgaleVector[NMax];   CntEvidence maiMiciSauEgaleVectorSumePartiale[NMax];   int NmaiMiciStrictVector;   int NmaiMiciSauEgaleVector;   int gcd(int x, int y) {     int r;     while (y) {       r = x % y;       x = y;       y = r;     }     return x;   }   void Insert(const int &x, const int &y, InsertType type, long long param = 0) {     int codh = (abs(x) + abs(y)) % MOD;     if (type == InsertCoord) {       for (vector<HashNode>::iterator it = H[codh].begin(); it != H[codh].end();            ++it) {         if (it->x == x && it->y == y) return;       }       H[codh].push_back(HashNode(x, y, 0, 0, 0));       return;     } else if (type == InsertCntStrict) {       for (vector<HashNode>::iterator it = H[codh].begin(); it != H[codh].end();            ++it) {         if (it->x == x && it->y == y) {           it->cntStrict = param;           return;         }       }       H[codh].push_back(HashNode(x, y, 0, param, 0));       return;     } else if (type == InsertCntNestrict) {       for (vector<HashNode>::iterator it = H[codh].begin(); it != H[codh].end();            ++it) {         if (it->x == x && it->y == y) {           it->cntNestrict = param;           return;         }       }       H[codh].push_back(HashNode(x, y, 0, 0, param));       return;     } else if (type == InsertIndexNestrict) {       for (vector<HashNode>::iterator it = H[codh].begin(); it != H[codh].end();            ++it) {         if (it->x == x && it->y == y) {           it->indexNestrict = param;           return;         }       }       H[codh].push_back(HashNode(x, y, param, 0, 0));       return;     }   }   void FindMaiMiciStrict(int x, int y) {     int st = 1, dr = lastIndexForSearch;     int ret = 0;     while (st <= dr) {       int mij = (st + dr) / 2;       if (CompareUnghiPolar(a[mij], Punct(x, y)) < 0) {         ret = mij;         st = mij + 1;       } else         dr = mij - 1;     }     Insert(x, y, InsertCntStrict, ret);     maiMiciStrictVector[++NmaiMiciStrictVector] = CntEvidence(x, y, ret);   }   void FindMaiMiciSauEgale(int x, int y) {     int st = 1, dr = lastIndexForSearch;     int ret = 0;     while (st <= dr) {       int mij = (st + dr) / 2;       if (CompareUnghiPolar(a[mij], Punct(x, y)) <= 0) {         ret = mij;         st = mij + 1;       } else         dr = mij - 1;     }     Insert(x, y, InsertCntNestrict, ret);     maiMiciSauEgaleVector[++NmaiMiciSauEgaleVector] = CntEvidence(x, y, ret);   }   long long QueryHash(int x, int y, QueryType type) {     x = -x;     y = -y;     if (y == 0) {       if (x < 0)         x = -1;       else if (x > 0)         x = 1;     } else if (x == 0) {       if (y < 0)         y = -1;       else if (y > 0)         y = 1;     } else {       int semnx = 1;       int semny = 1;       if (x < 0) {         x = -x;         semnx = -1;       }       if (y < 0) {         y = -y;         semny = -1;       }       int cmmdc = gcd(x, y);       x = x / cmmdc;       y = y / cmmdc;       x = x * semnx;       y = y * semny;     }     int codh = (abs(x) + abs(y)) % MOD;     for (vector<HashNode>::iterator it = H[codh].begin(); it != H[codh].end();          ++it) {       if (it->x == x && it->y == y) {         if (type == QueryCntStrict) return it->cntStrict;         if (type == QueryCntNestrict) return it->cntNestrict;         if (type == QueryIndexNestrict) return it->indexNestrict;       }     }     return -1;   }   void Solve() {     int loc;     loc = 0;     for (int i = 1; i <= N; ++i) {       if (a[i].y > 0 || (a[i].y == 0 && a[i].x > 0)) {         ++loc;         swap(a[i], a[loc]);       }     }     sort(a + 1, a + loc + 1);     sort(a + loc + 1, a + N + 1);     lastIndexForSearch = -1;     NmaiMiciStrictVector = 0;     NmaiMiciSauEgaleVector = 0;     int specialIndex = -1;     for (int i = 1; i <= N; ++i) {       if (GetAngle(a[i]) >= PI) {         if (a[i].y == 0) {           Insert(1, 0, InsertCoord);           FindMaiMiciStrict(1, 0);           FindMaiMiciSauEgale(1, 0);           continue;         }         if (a[i].x == 0) {           Insert(0, 1, InsertCoord);           FindMaiMiciStrict(0, 1);           FindMaiMiciSauEgale(0, 1);           continue;         }         int x, y;         x = -a[i].x;         y = -a[i].y;         int semnx = 1, semny = 1;         if (x < 0) {           x = -x;           semnx = -1;         }         if (y < 0) {           y = -y;           semny = -1;         }         int cmmdc = gcd(x, y);         x = x / cmmdc;         y = y / cmmdc;         x = x * semnx;         y = y * semny;         Insert(x, y, InsertCoord);         FindMaiMiciStrict(x, y);         FindMaiMiciSauEgale(x, y);       } else {         lastIndexForSearch = i;       }     }     bool foundOnRightOX = false;     specialIndex = NmaiMiciSauEgaleVector;     for (int i = 1; i <= N; ++i) {       if (a[i].y == 0 && a[i].x > 0) {         foundOnRightOX = true;         Insert(-1, 0, InsertCoord);         FindMaiMiciStrict(-1, 0);         FindMaiMiciSauEgale(-1, 0);       }     }     loc = 0;     for (int i = 1; i <= NmaiMiciStrictVector; ++i) {       if (maiMiciStrictVector[i].y > 0 ||           (maiMiciStrictVector[i].y == 0 && maiMiciStrictVector[i].x > 0)) {         ++loc;         swap(maiMiciStrictVector[i], maiMiciStrictVector[loc]);       }     }     sort(maiMiciStrictVector + 1, maiMiciStrictVector + loc + 1);     sort(maiMiciStrictVector + loc + 1,          maiMiciStrictVector + NmaiMiciStrictVector + 1);     for (int i = 1; i <= NmaiMiciStrictVector; ++i) {       maiMiciStrictVectorSumePartiale[i].x = maiMiciStrictVector[i].x;       maiMiciStrictVectorSumePartiale[i].y = maiMiciStrictVector[i].y;       maiMiciStrictVectorSumePartiale[i].cnt =           ((i > 1) ? (maiMiciStrictVectorSumePartiale[i - 1].cnt) : (0)) +           maiMiciStrictVector[i].cnt;     }     loc = 0;     for (int i = 1; i <= NmaiMiciSauEgaleVector; ++i) {       if (maiMiciSauEgaleVector[i].y > 0 ||           (maiMiciSauEgaleVector[i].y == 0 && maiMiciSauEgaleVector[i].x > 0)) {         ++loc;         swap(maiMiciSauEgaleVector[i], maiMiciSauEgaleVector[loc]);       }     }     sort(maiMiciSauEgaleVector + 1, maiMiciSauEgaleVector + loc + 1);     sort(maiMiciSauEgaleVector + loc + 1,          maiMiciSauEgaleVector + NmaiMiciSauEgaleVector + 1);     for (int i = 1; i <= NmaiMiciSauEgaleVector; ++i) {       maiMiciSauEgaleVectorSumePartiale[i].x = maiMiciSauEgaleVector[i].x;       maiMiciSauEgaleVectorSumePartiale[i].y = maiMiciSauEgaleVector[i].y;       maiMiciSauEgaleVectorSumePartiale[i].cnt =           ((i > 1) ? (maiMiciSauEgaleVectorSumePartiale[i - 1].cnt) : (0)) +           maiMiciSauEgaleVector[i].cnt;     }     for (int i = 1; i <= NmaiMiciSauEgaleVector; ++i) {       int index = i;       int x = maiMiciSauEgaleVectorSumePartiale[i].x;       int y = maiMiciSauEgaleVectorSumePartiale[i].y;       Insert(x, y, InsertIndexNestrict, index);     }     for (int i = 1; i <= NmaiMiciSauEgaleVector; ++i)       diferente[i] =           max(0LL, maiMiciSauEgaleVector[i].cnt - maiMiciStrictVector[i].cnt);     for (int i = 1; i <= NmaiMiciSauEgaleVector; ++i)       diferentePartiale[i] = diferentePartiale[i - 1] + diferente[i];     if (lastIndexForSearch != -1 && NmaiMiciSauEgaleVector != 0 &&         NmaiMiciStrictVector != 0) {       for (int i = lastIndexForSearch + 1; i <= N; ++i) {         if (a[i].y == 0 && a[i].x < 0) {           int index;           if (foundOnRightOX) {             index = specialIndex;           } else             index = NmaiMiciSauEgaleVector;           if (index <= 0) continue;           long long total = maiMiciSauEgaleVectorSumePartiale[index].cnt;           long long total2;           int jndex = QueryHash(a[i].x, a[i].y, QueryIndexNestrict);           if (jndex == -1) continue;           total2 = maiMiciSauEgaleVectorSumePartiale[jndex].cnt +                    1LL * (index - jndex) * maiMiciSauEgaleVector[jndex].cnt;           long long inPlus = diferentePartiale[index];           if (foundOnRightOX) inPlus = inPlus - diferentePartiale[jndex];           ans += max(0LL, total - total2 - inPlus);         } else {           int index;           index = NmaiMiciSauEgaleVector;           if (index <= 0) continue;           long long total = maiMiciSauEgaleVectorSumePartiale[index].cnt;           long long total2;           int jndex = QueryHash(a[i].x, a[i].y, QueryIndexNestrict);           if (jndex == -1) continue;           total2 = maiMiciSauEgaleVectorSumePartiale[jndex].cnt +                    1LL * (index - jndex) * maiMiciSauEgaleVector[jndex].cnt;           long long inPlus = diferentePartiale[index];           inPlus = inPlus - diferentePartiale[jndex];           ans += max(0LL, total - total2 - inPlus);         }       }     }   }   void EliminaDuplicate() {     int maiMici180, cnt;     long long total;     maiMici180 = 0;     total = 0LL;     for (int i = 1; i <= N; ++i) {       int x = a[i].x, y = a[i].y;       if (y > 0 || (y == 0 && x > 0)) ++maiMici180;     }     for (int i = 1; i <= N; ++i) {       if (a[i].y < 0) {         int x = -a[i].x;         int y = -a[i].y;         int st = 1, dr = maiMici180;         int val = 0;         while (st <= dr) {           int mij = (st + dr) / 2;           if (Determinant(Punct(0, 0), Punct(x, y), a[mij]) <= 0) {             val = mij;             st = mij + 1;           } else             dr = mij - 1;         }         total += max(0, maiMici180 - val);       }     }     cnt = 0;     for (int i = 1; i <= N; ++i)       if (a[i].y == 0 && a[i].x > 0) ++cnt;     ans = ans - 1LL * total * cnt;   }   int main() {     std::ios_base::sync_with_stdio(false);     cin >> N >> C >> D;     for (int i = 1; i <= N; ++i) {       int x, y;       cin >> x >> y;       a[i] = Punct(x - C, y - D);     }     Solve();     EliminaDuplicate();     for (int i = 0; i < MOD; ++i) H[i].clear();     for (int i = 1; i <= N; ++i) {       a[i].x = -a[i].x;       a[i].y = -a[i].y;     }     Solve();     EliminaDuplicate();     cout << ans <<   n ;     return 0;   }   long long sqr(const long long &x) { return x * x; }   long long Determinant(const Punct &A, const Punct &B, const Punct &C) {     return 1LL * (A.x - C.x) * (B.y - C.y) - 1LL * (A.y - C.y) * (B.x - C.x);   }   long long Dist2(const Punct &A, const Punct &B) {     return sqr(A.x - B.x) + sqr(A.y - B.y);   }   int GetCadran(const Punct &A) {     if (A.x > 0 && A.y > 0) return 1;     if (A.x < 0 && A.y > 0) return 2;     if (A.x < 0 && A.y < 0) return 3;     return 4;   }   long double GetAngle(const Punct &A) {     long double ret = atan2(A.y, A.x);     if (A.y < 0) ret = ret + PI * 2.0;     return ret;   }   long long CompareUnghiPolar(const Punct &A, const Punct &B) {     long long ret = Determinant(Punct(0, 0), A, B);     if (ret > 0) return -1;     if (ret < 0) return 1;     if (A.y == 0 && B.y == 0) {       if ((A.x > 0 && B.x > 0) || (A.x < 0 && B.x < 0)) return 0;       if (A.x > 0 && B.x < 0) return -1;       return 1;     }     if (A.x == 0 && B.x == 0) {       if ((A.y > 0 && B.y > 0) || (A.y < 0 && B.y < 0)) return 0;       if (A.y > 0 && B.y < 0) return -1;       return 1;     }     int semnxA, semnxB, semnyA, semnyB;     semnxA = semnxB = semnyA = semnyB = 1;     if (A.x < 0) semnxA = -1;     if (B.x < 0) semnxB = -1;     if (A.y < 0) semnyA = -1;     if (B.y < 0) semnyB = -1;     if (semnxA == semnxB && semnyA == semnyB) return 0;     if (semnyA == 1) return -1;     return 1;   }