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

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

template <class T>
struct Point {
    typedef Point P;
    T x, y;
    explicit Point(T x=0, T y=0) : x(x), y(y) {}
    bool operator<(P p) const { return tie(x,y) < tie(p.x,p.y); }
    bool operator==(P p) const { return tie(x,y)==tie(p.x,p.y); }
    P operator+(P p) const { return P(x+p.x, y+p.y); }
    P operator-(P p) const { return P(x-p.x, y-p.y); }
    P operator*(T d) const { return P(x*d, y*d); }
    P operator/(T d) const { return P(x/d, y/d); }
    T dot(P p) const { return x*p.x + y*p.y; }
    T cross(P p) const { return x*p.y - y*p.x; }
    T cross(P a, P b) const { return (a-*this).cross(b-*this); }
    T dist2() const { return x*x + y*y; }
    double dist() const { return sqrt((double)dist2()); }
    // angle to x-axis in interval [-pi, pi]
    double angle() const { return atan2(y, x); }
    P unit() const { return *this/dist(); } // makes dist()=1
    P perp() const { return P(-y, x); } // rotates +90 degrees
    P normal() const { return perp().unit(); }
    // returns point rotated 'a' radians ccw around the origin
    P rotate(double a) const {
        return P(x*cos(a)-y*sin(a),x*sin(a)+y*cos(a)); }
};

typedef Point<ll> P;
pair<vi, vi> ulHull(const vector<P>& S) {
    vi Q(sz(S)), U, L;
    iota(all(Q), 0);
    sort(all(Q), [&S](int a, int b){ return S[a] < S[b]; });
    trav(it, Q) {
#define ADDP(C, cmp) while (sz(C) > 1 && S[C[sz(C)-2]].cross(\
    S[it], S[C.back()]) cmp 0) C.pop_back(); C.push_back(it);
        ADDP(U, <=); ADDP(L, >=);
    }
    return {U, L};
}

vi convexHull(const vector<P>& S) {
    vi u, l; tie(u, l) = ulHull(S);
    if (sz(S) <= 1) return u;
    if (S[u[0]] == S[u[1]]) return {0};
    l.insert(l.end(), u.rbegin()+1, u.rend()-1);
    return l;
}

pair<LL,LL> neg(pair<LL,LL> d){
    return make_pair(-d.first, -d.second);
}

typedef Point<LL> P;
int main(){
    LL n;
    cin >> n;
    pair<LL,LL> a[n];
    pair<LL,LL> sum = make_pair(0,0);

    int test50 = 0;

    for(int i = 0; i < n; i++){
        cin >> a[i].first >> a[i].second;
        if(a[i].first == 1000000 && a[i].second == 999994){
            test50 = 1;
        }
        sum.first += a[i].first;
        sum.second += a[i].second;
        a[i].first *= n;
        a[i].second *= n;
    }

    map<pair<LL,LL>, LL> g;
    for(int i = 0; i < n; i++){
        a[i].first -= sum.first;
        a[i].second -= sum.second;
        g[a[i]]++;
        //cout << a[i].first << " " << a[i].second << endl;
    }
    for(int i = 0; i < n; i++){
        if(g.find(a[i]) != g.end() && g.find(neg(a[i])) != g.end()){
            g.erase(a[i]);
            g.erase(neg(a[i]));
        }
    }
    g.erase(make_pair(0,0));

    vector<pair<LL,LL> > pts;
    for(map<pair<LL,LL>, LL>::iterator it = g.begin(); it != g.end(); it++){
        if(it->second <= 0) continue;
        pts.push_back(it->first);
    }
    if(pts.size() == 0){
        cout << -1 << endl;
        return 0;
    }
    vector<P> z;
    for(int i = 0; i < pts.size(); i++){
        z.push_back(P(pts[i].first, pts[i].second));
        // cout << z[i].x << " " << z[i].y << endl;
    }
    vector<int> hull = convexHull(z);

    vector<P> checks;
    for(int i = 0; i < z.size(); i++){
        P del = z[0] + z[i];
        LL gg = __gcd(del.x, del.y);
        del.x /= gg; del.y /= gg;
        if(del.x < 0 || (del.x == 0 && del.y < 0)){
            del.x *= -1;
            del.y *= -1;
        }
        checks.push_back(del);
    }
    /*for(int j = 0; j < hull.size(); j++){
        int nj = (j+1) % (hull.size());
        P diff = z[hull[nj]] - z[hull[j]];
        LL maxcross = 0;
        LL mincross = 0;
        for(int c = 0; c < z.size(); c++){
            maxcross = max(maxcross, diff.cross(z[c]));
            mincross = min(mincross, diff.cross(z[c]));
        }
        vector<int> maxs;
        vector<int> mins;
        for(int c = 0; c < z.size(); c++){
            if(diff.cross(z[c]) == maxcross) maxs.push_back(c);
            if(diff.cross(z[c]) == mincross) mins.push_back(c);
        }
        for(int b = 0; b < maxs.size(); b++){
            for(int a = 0; a < mins.size(); a++){
                if(maxs[b] == mins[a]) continue;
                P del = z[maxs[b]] + z[mins[a]];
                LL gg = __gcd(del.x, del.y);
                del.x /= gg; del.y /= gg;
                if(del.x < 0 || (del.x == 0 && del.y < 0)){
                    del.x *= -1;
                    del.y *= -1;
                }
                checks.push_back(del);
            }
        }
    }*/

    map<pair<LL,LL>, int> fans;
    for(int j = 0; j < checks.size(); j++){
        map<LL,int> freq;
        for(int i = 0; i < z.size(); i++){
            freq[z[i].cross(checks[j])]++;
        }
        LL ok = 1;
        for(int i = 0; i < z.size(); i++){
            LL cur = z[i].cross(checks[j]);
            if(freq[cur] != freq[-cur]) ok = 0;
        }
        if(ok){
            fans[make_pair(checks[j].x, checks[j].y) ] = 1;
        }
    }
    cout << fans.size() << endl;
}


#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int N = 2005;
int x[N],y[N];
int n;
ll sx = 0,sy = 0;
struct cmp {
	bool operator()(const pii &lhs, const pii &rhs) const {
		return lhs.first * rhs.second < rhs.first * lhs.second;
	}
};
map<pair<ll,ll>,int> mp;
vector<pair<ll,ll> > a,b;
set<pair<ll,ll>,cmp> ans;
vector<ll> get(vector<pair<ll,ll> > now,ll ry,ll rx){
    vector<ll> ret;
    for(auto it : now){
        ret.push_back(rx*it.second+ry*it.first);
    }
    sort(ret.begin(),ret.end());
    return ret;
}

void check(ll ry,ll rx){
    if(get(a,ry,rx) == get(b,ry,rx)){
        if(rx < 0){
            rx = -rx;
            ry = -ry;
            ll gd = __gcd(rx,abs(ry));
            rx /= gd;
            ry /= gd;
        }
        ans.insert({rx,ry});
    }
}

int main(){
    cin >> n;
    for(int i = 1;i <= n;i ++){
        scanf("%d %d",&x[i],&y[i]);
        sx += x[i],sy += y[i];
        x[i] *= n;
        y[i] *= n;
    }
    for(int i = 1;i <= n;i ++){
        mp[{x[i],y[i]}] ++;
        mp[{2*sx - x[i],2*sy-y[i]}] --;
    }
    for(auto it : mp){
        for(int j = 0;j < abs(it.second);j ++){
            if(it.second > 0) a.push_back(it.first);
            else b.push_back(it.first);
        }
    }
    if(a.size() == 0) {
        puts("-1");
        return 0;
    }
    for(auto it : b){
        check(it.second - a[0].second,a[0].first - it.first);
    }
    cout << ans.size() << endl;
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int N = 2005;
int x[N],y[N];
int n;
ll sx = 0,sy = 0;
struct cmp {
	bool operator()(const pii &lhs, const pii &rhs) const {
		return lhs.first * rhs.second < rhs.first * lhs.second;
	}
};
set<pair<ll,ll> > ans;
set<int> s;
map<pair<ll,ll>,int> mp;
vector<pair<ll,ll> > a,b;

vector<ll> get(vector<pair<ll,ll> > v,ll ry,ll rx){
    vector<ll> ret;
    for(auto it : v){
        ret.push_back(rx*it.second+ry*it.first);
    }
    sort(ret.begin(),ret.end());
    return ret;
}

void check(ll ry,ll rx){
    if(get(a,ry,rx) == get(b,ry,rx)){
        if(rx < 0){
            rx = -rx;
            ry = -ry;
            ll gd = __gcd(rx,abs(ry));
            if(gd){
                rx /= gd;
                ry /= gd;
            }
        }
        if(rx == 0) ry = 1;
        if(ry == 0) rx = 1;
        ans.insert({rx,ry});
    }
}

int main(){
    cin >> n;
    for(int i = 1;i <= n;i ++){
        scanf("%d %d",&x[i],&y[i]);
        sx += x[i],sy += y[i];
        x[i] *= n;
        y[i] *= n;
    }
    for(int i = 1;i <= n;i ++){
        mp[{x[i],y[i]}] ++;
        mp[{2*sx - x[i],2*sy-y[i]}] --;
    }
    for(auto it : mp){
        for(int j = 0;j < abs(it.second);j ++){
            if(it.second > 0) a.push_back(it.first);
            else b.push_back(it.first);
        }
    }
    if(a.size() == 0) {
        puts("-1");
        return 0;
    }
    for(auto it : b){
        check(it.second - a[0].second,a[0].first - it.first);
    }
    cout << ans.size() << endl;

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int n,id[N],x;
struct P
{
	double x,y;
	P operator+(P a){return (P){x+a.x,y+a.y};}
	P operator-(P a){return (P){x-a.x,y-a.y};}
	double operator*(P a){return x*a.x+y*a.y;}
	P operator/(double a){return (P){x/a,y/a};}
	bool operator==(P a){return abs(x-a.x)<1e-9&&abs(y-a.y)<1e-9;}
}p[N],root,mid,vec;
pair<double,int> pp[N];
bool check(int pos)
{
	mid=(p[x]+p[pos])/2;
	vec=root-mid;
	vec=(P){vec.y,-vec.x};
	for (int i=1;i<=n;i++) pp[i]=make_pair(vec*p[i],i);
	sort(pp+1,pp+n+1);
	for (int i=1;i<=n;i++) id[pp[i].second]=i;
	if (id[x]+id[pos]!=n+1) return 0;
	double flag=pp[1].first+pp[n].first;
	for (int i=1;i<=n;i++)
	if (abs(pp[i].first+pp[n-i+1].first-flag)>1e-9) return 0;
	return 1;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++){scanf("%lf%lf",&p[i].x,&p[i].y);root=root+p[i];}
	root=root/n;
	bool inf=1;
	for(int i=1;i<=n;i++)
	{
		bool is=0;
		for(int j=1;j<=n;j++)if(p[i]+p[j]==root+root)is=1;
		if(!is)inf=0,x=i;
	}
	if(inf){puts("-1");return 0;}
	int ans=0;
	for (int i=1;i<=n;i++)if (check(i)) ans++;
	cout<<ans<<endl;
	return 0;
}


#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
#define N 2010
using namespace std;
const double eps = 1e-6;
struct node
{
    double x, y;
    friend node operator+(node a, node b)
    {
        return (node){a.x + b.x, a.y + b.y};
    }
    friend node operator-(node a, node b)
    {
        return (node){a.x - b.x, a.y - b.y};
    }
    friend double operator*(node a, node b)
    {
        return a.x * b.y - a.y * b.x;
    }
    friend bool operator==(node a, node b)
    {
        return fabs(a.x - b.x) < eps && fabs(a.y - b.y) < eps;
    }
} a[N], M, b[N];
node mid(node a, node b)
{
    return (node){(a.x + b.x) / 2, (a.y + b.y) / 2};
}
int n, id[N], num;
double len[N];
bool d[N], ans[N];
bool cmp1(int x, int y)
{
    return len[x] < len[y];
}
int main()
{
    //   freopen("D.in", "r", stdin);
    //   freopen("Dnew.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%lf%lf", &a[i].x, &a[i].y);
        M.x += a[i].x;
        M.y += a[i].y;
    }
    M.x /= n;
    M.y /= n;
    for (int i = 1; i <= n; i++)
        if (!d[i])
        {
            if (a[i] == M)
            {
                d[i] = 1;
                continue;
            }
            for (int j = 1; j < i; j++)
                if (!d[j] && mid(a[i], a[j]) == M)
                    d[i] = d[j] = 1;
        }
    int tmp = 0;
    for (int i = 1; i <= n; i++)
        if (!d[i])
            b[++tmp] = a[i];
    if (!tmp)
    {
        puts("-1");
        return 0;
    }
    swap(a, b);
    n = tmp;
    for (int i = 1; i <= n; i++)
        b[i] = M - mid(a[i], a[1]);
    for (int i = 1, j; i <= n; i++)
    {
        //cout << "v:" << v.x << ' ' << v.y << endl;
        for (int j = 1; j <= n; j++)
            len[j] = b[i] * (a[j] - M), id[j] = j;
        sort(id + 1, id + n + 1, cmp1);
        // for (int j = 1; j <= n; j++)
        //     cout << id[j] << ' ' << len[id[j]] << endl;
        // puts("");
        bool ok = 1;
        for (int j = 1; j <= (n + 1) / 2; j++)
            if (abs(len[id[j]] + len[id[n - j + 1]]) > eps)
            {
                ok = 0;
                break;
            }
        if (ok)
            ans[i] = 1, num++;
    }
    for (int i = 1; i <= n; i++)
        if (ans[i])
            for (int j = 1; j < i; j++)
                if (ans[j] && fabs(b[i] * b[j]) < eps)
                {
                    num--;
                    break;
                }
    printf("%d", num);
    return 0;
}
/*
10
0 5
1 0
2 3
3 2
4 6
5 9
6 1
7 8
8 4
9 7
*/


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

const double eps=1e-8;
const int MAXN=2005;
int cnt,n;
double d[MAXN];
int vis[MAXN];

struct Tpoint
{
	double x,y;
	inline Tpoint(){}
	inline Tpoint(double xx,double yy)
	{
		x=xx;
		y=yy;
	}

	inline Tpoint operator + (const Tpoint &A) const
	{
		return Tpoint(x+A.x,y+A.y);
	}

	inline Tpoint operator - (const Tpoint &A) const
	{
		return Tpoint(x-A.x,y-A.y);
	}

	inline Tpoint operator / (const double &A) const
	{
		return Tpoint(x/A,y/A);
	}

	inline double operator * (const Tpoint &A) const
	{
		return x*A.x+y*A.y;
	}

	inline double operator ^ (const Tpoint &A) const
	{
		return x*A.y-y*A.x;
	}
};
Tpoint p[MAXN];

struct Tline
{
	Tpoint s,t;
	inline Tline(){}
	inline Tline(Tpoint ss,Tpoint tt)
	{
		s=ss;t=tt;
	}

	inline double get_dis(Tpoint P)
	{
		return (t^(P-s))/sqrt(t*t);
	}

	inline bool sam(Tline L)
	{
		if(abs(t^L.t)>eps)
			return false;
		if(abs(t^(L.s-s))>eps)
			return false;
		return true;
	}
};
Tline l[MAXN];

int main()
{
//	freopen("D.in","r",stdin);
//	freopen("D.out","w",stdout);

	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%lf%lf",&p[i].x,&p[i].y);

	if(n<=2)
	{
		printf("-1\n");
		return 0;
	}
	if(p[1]*p[1]<eps)
		swap(p[1],p[2]);

	Tpoint O(0,0);
	for(int i=1;i<=n;++i)
		O=O+p[i];
	O=O/n;

	int tmp=0,pos;
	for(int i=1;i<=n;++i)
	{
		bool flag=false;
		for(int j=1;j<=n;++j)
		{
			if( ((p[i]+p[j])*(p[i]+p[j])) <eps || ( (((p[i]+p[j])/2-O)*((p[i]+p[j])/2-O)) <eps) )
			{
				flag=true;
				break;
			}
		}
		if(flag)
			++tmp;
		else
			pos=i;
	}

	if(tmp==n)
	{
		printf("-1\n");
		return 0;
	}

	swap(p[1],p[pos]);
	for(int i=1;i<=n;++i)
	{
		if( ((p[1]+p[i])*(p[1]+p[i])) <eps)
			continue;
		if( (((p[1]+p[i])/2-O)*((p[1]+p[i])/2-O)) <eps)
			continue;

		Tpoint tp=(p[1]+p[i])/2;
		Tline tl=Tline(tp,tp-O);
		for(int j=1;j<=n;++j)
			d[j]=tl.get_dis(p[j]);

		sort(d+1,d+n+1);

		bool flag=true;
		for(int i=1;i<=n;++i)
		{
			if(d[i]+d[n-i+1]>eps)
			{
				flag=false;
				break;
			}
		}
		if(flag)
			l[++cnt]=tl;
	}

	int ans=0;
	for(int i=1;i<=cnt;++i)
	{
		int flag=true;
		for(int j=1;j<i;++j)
			if(l[i].sam(l[j]))
			{
				flag=false;
				break;
			}
		if(flag)
			++ans;
	}
	printf("%d\n",ans);
//	printf("%d\n",clock());

	return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iostream>
#include <iomanip>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <sstream>
#include <tuple>
#include <vector>

using namespace std;
using namespace chrono;

#ifdef DEBUG
	#define LOCAL_INPUT_FILE
#else
	//#define USE_FILE_IO
#endif

#ifdef USE_FILE_IO
	#define INPUT_FILE "input.txt"
	#define OUTPUT_FILE "output.txt"
	#define cin ____cin
	#define cout ____cout
	ifstream cin(INPUT_FILE);
	ofstream cout(OUTPUT_FILE);
#else
	#ifdef LOCAL_INPUT_FILE
		#define cin ____cin
		ifstream cin("input.txt");
	#endif
#endif

const int infinity = (int)1e9 + 42;
const int64_t llInfinity = (int64_t)1e18 + 256;
const int module = (int)1e9 + 7;
const long double eps = 1e-8;

mt19937_64 randGen(system_clock().now().time_since_epoch().count());

inline void raiseError(string errorCode) {
	cerr << "Error : " << errorCode << endl;
	exit(42);
}

namespace Fractions {
template<class Int>
class Fraction {
private:
	Int n;
	Int d;

	inline static Int gcd(const Int& a, const Int& b) {
		return (b == Int(0)) ? a : gcd(b, a % b);
	}

	inline void truncate() {
		Int g = gcd(abs(n), abs(d));
		n /= g;
		d /= g;
		if (d < Int(0)) {
			n *= -1;
			d *= -1;
		}
	}
public:
	Fraction()
		: n(0), d(1) {
	}

	Fraction(const Int& v)
		: n(v), d(1) {
	}

	explicit Fraction(string s) {
		size_t p = s.find('/');
		if (p == string::npos) {
			istringstream nIs(s); nIs >> n;
			d = Int(1);
		} else {
			istringstream nIs(s.substr(0, p)); nIs >> n;
			istringstream dIs(s.substr(p+1));  dIs >> d;
		}
		truncate();
	}

	Fraction(const Int& n, const Int& d)
		: n(n), d(d) {
		truncate();
	}

	inline string toString() const {
		ostringstream os; os << *this;
		return os.str();
	}

	inline Int numerator() const {
		return n;
	}

	inline Int denominator() const {
		return d;
	}

	inline friend istream& operator>>(istream& is, Fraction& a) {
		string s; is >> s;
		a = Fraction(s);
		return is;
	}

	inline friend ostream& operator<<(ostream& os, const Fraction& a) {
		if (a.d == Int(1)) {
			return os << a.n;
		} else {
			return os << a.n << "/" << a.d;
		}
	}

	inline Fraction& operator=(const string& s) {
		return *this = Fraction(s);
	}

	inline Fraction& operator=(const Int& v) {
		return *this = Fraction(v);
	}

	inline friend bool operator<(const Fraction& a, const Fraction& b) {
		return a.n * b.d < b.n * a.d;
	}

	inline friend bool operator<=(const Fraction& a, const Fraction& b) {
		return a.n * b.d <= b.n * a.d;
	}

	inline friend bool operator>(const Fraction& a, const Fraction& b) {
		return a.n * b.d > b.n * a.d;
	}

	inline friend bool operator>=(const Fraction& a, const Fraction& b) {
		return a.n * b.d >= b.n * a.d;
	}

	inline friend bool operator==(const Fraction& a, const Fraction& b) {
		return a.n * b.d == b.n * a.d;
	}

	inline friend bool operator!=(const Fraction& a, const Fraction& b) {
		return a.n * b.d != b.n * a.d;
	}

	inline friend Fraction operator+(const Fraction& a) {
		return a;
	}

	inline friend Fraction operator-(const Fraction& a) {
		return Fraction(-a.n, a.d);
	}

	inline Fraction& operator++() {
		n += d;
		truncate();
		return *this;
	}

	inline Fraction operator++(int) {
		Fraction ret = *this;
		++(*this);
		return ret;
	}

	inline Fraction& operator--() {
		n -= d;
		truncate();
		return *this;
	}

	inline Fraction operator--(int) {
		Fraction ret = *this;
		--(*this);
		return ret;
	}

	inline friend Fraction operator+(const Fraction& a, const Fraction& b) {
		return Fraction(a.n * b.d + a.d * b.n, a.d * b.d);
	}

	inline friend Fraction operator-(const Fraction& a, const Fraction& b) {
		return Fraction(a.n * b.d - a.d * b.n, a.d * b.d);
	}

	inline friend Fraction operator*(const Fraction& a, const Fraction& b) {
		return Fraction(a.n * b.n, a.d * b.d);
	}

	inline friend Fraction operator/(const Fraction& a, const Fraction& b) {
		return Fraction(a.n * b.d, a.d * b.n);
	}

	inline Fraction& operator+=(const Fraction& delta) {
		return *this = *this + delta;
	}

	inline Fraction& operator-=(const Fraction& delta) {
		return *this = *this - delta;
	}

	inline Fraction& operator*=(const Fraction& delta) {
		return *this = *this * delta;
	}

	inline Fraction& operator/=(const Fraction& delta) {
		return *this = *this / delta;
	}

	inline long double toDouble() {
		return (long double)n / d;
	}

	inline friend Fraction abs(Fraction a) {
		a.n = abs(a.n);
		a.d = abs(a.d);
		return a;
	}
};
}

using Fraction = Fractions::Fraction<int64_t>;

struct Point {
	int64_t x, y;

	auto toPair() {
		return make_pair(x, y);
	}

	inline friend ostream & operator <<(ostream &os, const Point &p) {
		return os << "{" << p.x << ", " << p.y << "}";
	}
};

signed main() {
	#ifndef USE_FILE_IO
		ios_base::sync_with_stdio(false);
	#endif
	int n; cin >> n;
	vector<Point> v(n);
	int64_t sumX = 0, sumY = 0;
	for (int i = 0; i < n; i++) {
		cin >> v[i].x >> v[i].y;
		sumX += v[i].x;
		sumY += v[i].y;
	}
	Fraction pX {sumX, n}, pY {sumY, n};
	vector<char> active(n, true);
	for (int i = 0; i < n; i++) {
		if (v[i].x == pX && v[i].y == pY) {
			active[i] = false;
		}
		if (!active[i]) {
			continue;
		}
		for (int j = 0; j < i; j++) {
			if (!active[j]) {
				continue;
			}
			if (v[i].x + v[j].x == 2 * pX && v[i].y + v[j].y == 2 * pY) {
				active[i] = active[j] = false;
				break;
			}
		}
	}
	vector<Point> q;
	for (int i = 0; i < n; i++) {
		if (active[i]) {
			q.push_back(v[i]);
		}
	}
	if (q.empty()) {
		cout << -1 << endl;
		return 0;
	}

	set<Fraction> anses;
	int qs = q.size();

	auto check = [&](const Fraction &x, const Fraction &y) {
		if (2*pX == q[0].x + x) {
			return;
		}

		Fraction fK = -(2*pY - q[0].y - y) / (2*pX - q[0].x - x);
		long double k = fK.toDouble();
		long double pivot = pX.toDouble() * k + pY.toDouble();

		vector<long double> p(qs);
		for (int j = 0; j < qs; j++) {
			p[j] = q[j].x * k + q[j].y;
		}
		sort(p.begin(), p.end());
		bool ok = true;
		for (int j = 0; j < qs; j++) {
			if (abs(2 * pivot - p[j] - p[qs - j - 1]) > (long double)1e-9) {
				ok = false;
				break;
			}
		}
		if (ok) {
			anses.insert(fK);
		}
	};

	for (int i = 1; i < qs; i++) {
		check(q[i].x, q[i].y);
	}
	check(pX, pY);

	int ans = anses.size();
	auto v2 = v;
	set<int64_t> uniqueX;
	sort(v2.begin(), v2.end(), [&](Point a, Point b) -> bool {
		return a.x < b.x;
	});
	for (int i = 0; i < n; i++) {
		uniqueX.insert(v2[i].x + v2[n-i-1].x);
	}
	ans += uniqueX.size() == 1;

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


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

using ll=long long;
//#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
ll mask(int i){
	return (ll(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
	static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
	#endif
	return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
void myshuffle(vc<t>&a){
	rep(i,si(a))swap(a[i],a[rand_int(0,i)]);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

//#define GEOF

#ifdef GEOF
using ld=long double;
#else
using ld=ll;
#endif
using cm=complex<signed>;
#define x real()
#define y imag()
const ld eps=1e-8;
#ifdef GEOF
const ld PI=acos(ld(-1));
#endif
int sgn(ld a){return a<-eps?-1:(a>eps?1:0);}
ld rabs(cm a){return max(abs(a.x),abs(a.y));}
ld signed_rabs(cm a){
	if(abs(a.x)>abs(a.y))return a.x;
	else return a.y;
}
ld dot(cm a,cm b){return ld(a.x)*b.x+ld(a.y)*b.y;}
ld crs(cm a,cm b){return ld(a.x)*b.y-ld(a.y)*b.x;}
ld crs(cm a,cm b,cm c){return crs(b-a,c-a);}
int ccw(cm a,cm b){return sgn(crs(a,b));}
int ccw(cm a,cm b,cm c){return ccw(b-a,c-a);}
#ifdef GEOF
auto cmless=[](cm a,cm b){
	int s=sgn(a.x-b.x);
	if(s)return s<0;
	else return sgn(a.y-b.y)<0;
};
#else
auto cmless=[](const cm&a,const cm&b){
	return a.x!=b.x?a.x<b.x:a.y<b.y;
};
#endif
bool cmeq(cm a,cm b){
	return sgn(a.x-b.x)==0&&sgn(a.y-b.y)==0;
};
//(-pi,0](0,pi]
int argtype(cm a){
	if(sgn(a.y)==0)return a.x<0?1:0;
	return a.y<0?0:1;
}
int argcmp(cm a,cm b){
	int at=argtype(a),bt=argtype(b);
	if(at!=bt)return at<bt?-1:1;
	return -ccw(a,b);
};
bool argless(cm a,cm b){return argcmp(a,b)<0;}
//(-2)[a,-1](0)[b,1](2)
int bet(cm a,cm b,cm c){
	cm d=b-a;
	ld e=dot(d,c-a);
	if(sgn(e)<=0)return sgn(e)-1;
	return sgn(e-norm(d))+1;
}
//AOJ0153
//0-no,1-edge,2-in
int cont(cm a,cm b,cm c,cm d){
	if(ccw(a,b,c)==-1)
		swap(b,c);
	return min({ccw(a,b,d),ccw(b,c,d),ccw(c,a,d)})+1;
}
#ifdef GEOF
//AOJ1183
int qeq(ld a,ld b,ld c,ld&d,ld&e){
	ld f=b*b-4*a*c;
	if(sgn(f)<0)return 0;
	ld g=sqrt(max(f,ld(0)));
	d=(-b+g)/(2*a);
	e=(-b-g)/(2*a);
	return sgn(f)+1;
}
//AOJ1183
//arg between ab
//assume given lengths are valid
ld arg(ld a,ld b,ld c){
	return acos(min(max((a*a+b*b-c*c)/(2*a*b),ld(-1)),ld(1)));
}
//AOJ2233
//a->b->c と進むときに曲がる角度
//a-b-cが一直線上にあれば0が帰る
ld turn(cm a,cm b,cm c){
	return arg((c-b)/(b-a));
}
#endif
cm rot90(cm a){
	return cm(-a.y,a.x);
}

#ifndef GEOF
int gcd(int a,int b){return b?gcd(b,a%b):a;}
cm normdir(cm a){
	if(a==cm(0,0))return a;
	int g=gcd(abs(a.x),abs(a.y));
	return cm(a.x/g,a.y/g);
}
#endif

struct ysp{
	struct compare{
		bool operator()(const cm&a,const cm&b)const{
			return cmless(a,b);
		}
	};
	multiset<cm,compare> p,q;
	void fin(){
		auto itr=q.bg;
		while(itr!=q.ed){
			bool ok=false;
			if(si(p)<=1){
				ok=true;
			}else{
				if(ccw(*p.bg,*p.rbegin(),*itr)==0)
					ok=true;
			}
			if(!ok)break;
			p.insert(*itr);
			itr=q.erase(itr);
		}
	}
	void add(cm a){
		q.insert(a);
		fin();
	}
	void rem(cm a){
		auto itr=p.find(a);
		if(itr!=p.ed){
			p.erase(itr);
		}else{
			itr=q.find(a);
			assert(itr!=q.ed);
			q.erase(itr);
		}
		fin();
	}
	bool val(cm&dir){
		if(si(q))return false;
		assert(si(p));
		dir=*p.bg-*p.rbegin();
		if(dir==cm(0,0)){
			print(-1);
			exit(0);
		}
		if(cmless(dir,cm(0,0)))dir=-dir;
		dir=normdir(dir);
		return true;
	}
};

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);

	int n;cin>>n;
	if(n<=2){
		print(-1);
		return 0;
	}
	vc<cm> a(n);
	rep(i,n){
		int p,q;cin>>p>>q;
		a[i]=cm(p,q);
	}

	vi idx(n);iota(all(idx),0);
	sort(all(idx),[&](int i,int j){return cmless(a[i],a[j]);});
	reverse(all(idx));
	vi pos(n);
	rep(i,n)pos[idx[i]]=i;

	struct T{
		cm v;
		ll a,b;
		int i,j;
		bool operator<(const T&r)const{
			int s=argcmp(v,r.v);
			if(s)return s<0;
			if(a!=r.a)return a<r.a;
			return b<r.b;
		}
	};
	vc<T> evs;evs.reserve(n*(n-1));
	rep(i,n)rep(j,n)if(i!=j){
		cm dir=normdir(a[j]-a[i]);
		evs.pb({-rot90(dir),dot(a[i],dir),dot(a[j],dir),i,j});
	}

	sort(all(evs));
	evs.resize(n*(n-1)/2);

	ysp mk;

	vi now(n);
	auto add=[&](int i){
		chmin(i,n-1-i);
		if(now[i])return;
		mk.add(cm(a[idx[i]]+a[idx[n-1-i]]));
		now[i]=1;
	};
	auto rem=[&](int i){
		chmin(i,n-1-i);
		if(!now[i])return;
		mk.rem(cm(a[idx[i]]+a[idx[n-1-i]]));
		now[i]=0;
	};

	rep(i,n)add(i);

	vc<cm> ans;
	for(auto eve:evs){
		int i=eve.i,j=eve.j;
		i=pos[i],j=pos[j];
		assert(i-1==j);
		rem(i);
		rem(j);
		swap(idx[i],idx[j]);
		swap(pos[idx[i]],pos[idx[j]]);
		add(i);
		add(j);
		cm tmp;
		if(mk.val(tmp))ans.pb(tmp);
	}

	sort(all(ans),cmless);
	ans.erase(unique(all(ans),cmeq),ans.ed);
	print(si(ans));
}


#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair <int, int> pii;

inline int Read()
{
	int x = 0, f = 1, c = getchar();
	for (; !isdigit(c); c = getchar())
		if (c == '-')
			f = -1;
	for (;  isdigit(c); c = getchar())
		x = x * 10 + c - '0';
	return x * f;
}

typedef long double ldb;

#define double ldb

const int MAXN = 2005;
const double eps = 1e-9;

struct Point
{
	double x, y;
	Point(double _x = 0, double _y = 0) { x = _x, y = _y; }
	Point operator + (const Point &b) const { return Point(x + b.x, y + b.y); }
	Point operator - (const Point &b) const	{ return Point(x - b.x, y - b.y); }
	Point operator * (const double &b) const { return Point(x * b, y * b); }
	bool operator == (const Point &b) const { return x == b.x && y == b.y; }
	double operator * (const Point &b) const { return x * b.y - y * b.x; }
	inline double Len() { return sqrt(x * x + y * y); }
} sum, p[MAXN];

vector <Point> ans;
bool b[MAXN];
int n;

inline Point Get(Point p)
{
	double l = p.Len();
	return Point(p.x / l, p.y / l);
}

int main()
{
#ifdef wxh010910
	freopen("data.in", "r", stdin);
#endif
	n = Read();
	for (int i = 1; i <= n; i ++)
		p[i].x = Read(), p[i].y = Read(), sum = sum + p[i];
	for (int i = 1; i <= n; i ++)
		for (int j = i; j <= n; j ++)
			if ((p[i] + p[j]) * n == sum * 2)
				b[i] = 1, b[j] = 1;
	sum.x /= n, sum.y /= n;
	int lst_n = n;
	n = 0;
	for (int i = 1; i <= lst_n; i ++)
		if (!b[i])
			p[++ n] = p[i];
	if (!n)
		return puts("-1"), 0;
	for (int i = 1; i <= n; i ++)
		p[i] = p[i] - sum;
	for (int i = 1; i <= n; i ++)
	{
		Point e = Get(p[1] + p[i]);
		vector <double> a, b;
		for (int j = 1; j <= n; j ++)
		{
			double v = p[j] * e;
			if (fabs(v) > eps)
				if (v > 0)
					a.pb(v);
				else
					b.pb(-v);
		}
		if (a.size() != b.size())
			continue;
		sort(a.begin(), a.end());
		sort(b.begin(), b.end());
		bool flg = true;
		for (int j = 0; j < a.size() && flg; j ++)
			if (fabs(a[j] - b[j]) > eps)
				flg = false;
		if (flg)
			ans.pb(e);
	}
	int ret = 0;
	for (int i = 0; i < ans.size(); i ++)
	{
		bool flg = true;
		for (int j = 0; j < i && flg; j ++)
			if (fabs((ans[i] + ans[j]).Len()) < eps || fabs((ans[i] - ans[j]).Len()) < eps)
				flg = false;
		if (flg)
			ret ++;
	}
	return printf("%d\n", ret), 0;
}


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

const int N = 2005;

#define double long double

const double ep = 1e-10;

struct pnt {
	double x, y;
    pnt() {x = y = 0;}
    pnt(double xx, double yy) {x = xx, y = yy;}
    pnt operator + (pnt a) {return pnt(x + a.x, y + a.y);}
    void in() {int xx, yy; cin >> xx >> yy; x = xx, y = yy;}
    double operator ^ (const pnt &a) const {return x*a.y-y*a.x;}
    bool operator < (const pnt &a) const {return x != a.x ? x < a.x : y < a.y;}
    bool int_pnt(pnt &a) {
        int xx = x + (x > 0 ? 0.5 : -0.5), yy = y + (y > 0 ? 0.5 : -0.5);
        if (abs(x-xx) < ep && abs(y-yy) < ep) {
            a = pnt(xx, yy);
            return 1;
        }
        return 0;
    }
} p[N], M, MM;

vector <pnt> P;

int n;

map <pnt, int> h;

bool opp[N];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i ++) {
		p[i].in();
		M = M + p[i];
        h[p[i]] = i;
    }
    M.x /= n, M.y /= n;
    MM.x = M.x * 2, MM.y = M.y * 2;
    for (int i = 1; i <= n; i ++) if (!opp[i]) {
        pnt pp = pnt(MM.x-p[i].x, MM.y-p[i].y), qq;
        if (pp.int_pnt(qq) && h.count(qq)) {
            int t = h[qq];
            opp[t] = 1; opp[i] = 1;
        }
    }
    for (int i = 1; i <= n; i ++) if (!opp[i]) P.push_back(p[i]);
    if (P.empty()) puts("-1");
    else {
        pnt A = P[0];
        int ans = 0;
        vector <pnt> D;
        for (auto x : P) {
            pnt AM = A + x;
            AM.x /= 2, AM.y /= 2;
            pnt d = pnt(M.x - AM.x, M.y - AM.y);
            vector <double> pos, neg;
            for (auto y : P) {
                double l = d ^ pnt(y.x - AM.x, y.y - AM.y);
                if (abs(l) < ep) continue;
                if (l < 0) neg.push_back(-l);
                else pos.push_back(l);

            }
            if (neg.size() != pos.size()) continue;
            sort(neg.begin(), neg.end());
            sort(pos.begin(), pos.end());
            bool flag = 0;
            for (int i = 0; i < pos.size(); i ++) if (abs(pos[i]-neg[i]) > ep) flag = 1;
            if (!flag) D.push_back(d);
        }
        for (auto &x : D) {
            if (x.y < 0) x.y = -x.y, x.x = -x.x;
            if (x.y == 0 && x.x < 0) x.x = -x.x;
        }
        sort(D.begin(), D.end(), [](const pnt &x, const pnt &y) {
            return (x^y) > 0;
		});
        int sz = D.size();
        for (int i = 0, j; i < sz; i = j) {
            for (j = i; j < sz && (D[i]^D[j])==0; j ++);
            ans ++;
        }
        printf("%d\n", ans);
    }
	return 0;
}


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

#define ms(s, n) memset(s, n, sizeof(s))
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define FORd(i, a, b) for (int i = (a) - 1; i >= (b); i--)
#define FORall(it, a) for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
#define sz(a) int((a).size())
#define present(t, x) (t.find(x) != t.end())
#define all(a) (a).begin(), (a).end()
#define uni(a) (a).erase(unique(all(a)), (a).end())
#define pb push_back
#define pf push_front
#define mp make_pair
#define fi first
#define se second
#define prec(n) fixed<<setprecision(n)
#define bit(n, i) (((n) >> (i)) & 1)
#define bitcount(n) __builtin_popcountll(n)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pi> vii;
const int MOD = (int) 1e9 + 7;
const int FFTMOD = 1007681537;
const int INF = (int) 1e9;
const ll LINF = (ll) 1e18;
const ld PI = acos((ld) -1);
const ld EPS = 1e-9;
inline ll gcd(ll a, ll b) {ll r; while (b) {r = a % b; a = b; b = r;} return a;}
inline ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
inline ll fpow(ll n, ll k, int p = MOD) {ll r = 1; for (; k; k >>= 1) {if (k & 1) r = r * n % p; n = n * n % p;} return r;}
template<class T> inline int chkmin(T& a, const T& val) {return val < a ? a = val, 1 : 0;}
template<class T> inline int chkmax(T& a, const T& val) {return a < val ? a = val, 1 : 0;}
inline ll isqrt(ll k) {ll r = sqrt(k) + 1; while (r * r > k) r--; return r;}
inline ll icbrt(ll k) {ll r = cbrt(k) + 1; while (r * r * r > k) r--; return r;}
inline void addmod(int& a, int val, int p = MOD) {if ((a = (a + val)) >= p) a -= p;}
inline void submod(int& a, int val, int p = MOD) {if ((a = (a - val)) < 0) a += p;}
inline int mult(int a, int b, int p = MOD) {return (ll) a * b % p;}
inline int inv(int a, int p = MOD) {return fpow(a, p - 2, p);}
inline int sign(ld x) {return x < -EPS ? -1 : x > +EPS;}
inline int sign(ld x, ld y) {return sign(x - y);}
#define db(x) cerr << #x << " = " << (x) << " ";
#define endln cerr << "\n";

struct PT {
    int x, y;
    PT(int x = 0, int y = 0) : x(x), y(y) {}
    PT operator - (const PT& rhs) {return PT(x - rhs.x, y - rhs.y);}
    PT operator + (const PT& rhs) {return PT(x + rhs.x, y + rhs.y);}
    int operator == (const PT& rhs) const {return x == rhs.x && y == rhs.y;}
    int operator != (const PT& rhs) const {return !(x == rhs.x && y == rhs.y);}
    int operator < (const PT& rhs) const {return mp(x, y) < mp(rhs.x, rhs.y);}
};

inline long long cross(PT a, PT b) {
    return (long long) a.x * b.y - (long long) a.y * b.x;
}

const int maxn = 4000 + 5;
int n;

int dj[maxn];
int size[maxn];
int odds;
int ncache;
pair<int*, int> cache[maxn * maxn / 2];

void init(int k) {
    FOR(i, 0, k) dj[i] = i, size[i] = 1;
    odds = k;
}
void reset() {
    while (ncache > 0) {
        *cache[ncache - 1].fi = cache[ncache - 1].se;
        ncache--;
    }
}
int find(int u) {
    if (dj[u] == u) return dj[u];
    cache[ncache++] = mp(&dj[u], dj[u]);
    return dj[u] = find(dj[u]);
}
void join(int u, int v) {
    int p = find(u);
    int q = find(v);
    if (p != q) {
        cache[ncache++] = mp(&dj[p], dj[p]);
        dj[p] = q;
        cache[ncache++] = mp(&odds, odds);
        if (size[p] & 1) {
            odds--;
        }
        if (size[q] & 1) {
            odds--;
        }
        cache[ncache++] = mp(&size[q], size[q]);
        size[q] += size[p];
        if (size[q] & 1) {
            odds++;
        }
    }
}

void solve() {
    srand(time(NULL));
    cin >> n;
    vector<PT> p(n);
    PT cen;
    map<PT, int> hs, tmp;
    for (PT& q : p) {
        cin >> q.x >> q.y;
        cen = cen + q;
        q.x *= n, q.y *= n;
        hs[q] ^= 1;
        tmp[q] = 1;
    }
    FOR(i, 0, n) {
        PT q = cen + cen - p[i];
        hs[q] ^= 1;
    }
    p.clear();
    for (auto it : hs) {
        if (it.fi != cen && it.se) {
            p.pb(it.fi);
        }
    }
    if (!sz(p)) {
        cout << -1 << "\n";
        return;
    }
    unordered_map<long long, vii> hs2;
    map<long long, int> can;
    FOR(i, 0, sz(p)) FOR(j, i + 1, sz(p)) if (tmp.count(p[i]) + tmp.count(p[j]) == 1) {
        PT q = p[i] - p[j];
        if (q.y < 0 || (!q.y && q.x < 0)) q.x *= -1, q.y *= -1;
        int g = __gcd(abs(q.x), abs(q.y));
        q.x /= g, q.y /= g;
        long long t = (long long) (q.x + INF) * (INF + INF) + (q.y + INF);
        if (!i) {
            can[t] = 1;
            hs2[t].pb(mp(i, j));
        }
        else if (can.count(t)) {
            hs2[t].pb(mp(i, j));
        }
    }
    int k = sz(p);
    init(k);
    int res = 0;
    for (auto it : hs2) if (can[it.fi]) {
        reset();
        for (auto x : it.se) {
            join(x.fi, x.se);
        }
        if (!odds) {
            res++;
        }
    }
    cout << res << "\n";
}

int main(int argc, char* argv[]) {
    ios_base::sync_with_stdio(0), cin.tie(0);
    if (argc > 1) {
        assert(freopen(argv[1], "r", stdin));
    }
    if (argc > 2) {
        assert(freopen(argv[2], "wb", stdout));
    }
    solve();
    cerr << "\nTime elapsed: " << 1000 * clock() / CLOCKS_PER_SEC << "ms\n";
    return 0;
}


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

#define forn(i,n) for(int i=0;i<(int)(n);i++)
#define si(c) ((int)(c).size())
#define forsn(i,s,n) for(int i = (int)(s); i<((int)n); i++)
#define dforsn(i,s,n) for(int i = (int)(n)-1; i>=((int)s); i--)
#define all(c) (c).begin(), (c).end()
#define D(a) cerr << #a << "=" << a << endl;
#define pb push_back
#define eb emplace_back
#define mp make_pair

typedef long long int ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<long,long> pll;

const int N = 2020;

int n;
ll x[N], y[N], px, py;
set<pll> points;

ll gcd(ll a, ll b) { return a ? gcd(b%a,a) : b; }
void normal(pll &n) {
    int d = gcd(n.first, n.second);
    n.first /= d;
    n.second /= d;
    if (n.first < 0) {
        n.first = -n.first;
        n.second = -n.second;
    }
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

    cin >> n;
    forn(i,n) {
        cin >> x[i] >> y[i];
        px += x[i];
        py += y[i];
        x[i] *= n;
        y[i] *= n;
        points.emplace(x[i], y[i]);
    }

    forn(i,n) {
        auto sx = 2*px - x[i];
        auto sy = 2*py - y[i];
        auto p = mp(x[i], y[i]);
        auto s = mp(sx,sy);
        if (points.count(s)) {
            points.erase(s);
            if (points.count(p)) points.erase(p);
        }
    }

    n = 0;
    for (auto &xy : points) {
        x[n] = xy.first;
        y[n] = xy.second;
        n++;
    }

    if (n < 2) {
        cout << -1 << endl;
        return 0;
    }

    set<pll> ans;
    forn(i,n) {
        pll q = mp(x[0] + x[i], y[0] + y[i]);
        pll p = mp(2*px,2*py);
        pll v = mp(q.first - p.first, q.second-p.second);
        pll norm = mp(-v.second, v.first);
        normal(norm);

        vector<ll> d;
        forn(i,n) d.eb(norm.first * x[i] + norm.second * y[i]);
        sort(all(d));

        auto goal = d.front() + d.back();
        int sz = si(d), ok = 1;
        for (int i = 0, j = sz-1; i < j; i++, j--) {
            ok &= d[i] + d[j] == goal;
        }
        if (ok) ans.insert(norm);
    }
    //for (auto xy: ans) cerr << xy.first << ' ' << xy.second << endl;
    cout << si(ans) << endl;

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

int allSame, currCnt, N, M, nr, X[4002017], Y[4002017], inv[2017];
double PI = acos (-1.0);

struct point
{
    int x, y;
    point () {}
    point (int _x, int _y):
        x (_x), y (_y) {}
    bool operator < (const point &other) const
    {
        if (x == other.x) return y < other.y;
        return x < other.x;
    }
}A[2017], b[2017];

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

bool det (point a, point b, point c)
{
    return (1LL * a.x * b.y + 1LL * b.x * c.y + 1LL * c.x * a.y -
            1LL * a.x * c.y - 1LL * b.x * a.y - 1LL * c.x * b.y == 0LL);
}

struct unghi
{
    long long sus, jos, side;

    unghi () {}

    unghi (long long x, long long y)
    {
        if (x > 0) side = -1;
        else side = (x != 0);
        sus = y, jos = x;
        if (jos < 0) sus = -y, jos = -x;
    }

    bool operator == (const unghi &other) const
    {
        return (side == other.side && 1LL * sus * other.jos == 1LL * jos * other.sus);
    }

    bool operator < (const unghi &other) const
    {
        if (side != other.side) return side < other.side;
        return 1LL * sus * other.jos < 1LL * other.sus * jos;
    }

    void print (string s)
    {
        printf ("(%I64d, %I64d, %I64d)  %.10f%s", sus, jos, side, atan ((double) sus / jos * side) * 180.0 / PI, s.c_str ());
    }
};

struct query
{
    unghi m;
    int where;

    bool operator < (const query &other) const
    {
        if (m == other.m)
        {
            if (1LL * where * other.where < 0) return (where > other.where);
            if (where < 0) return 0;
            int i = X[where], j = Y[where], k = X[other.where], p = Y[other.where];
            if (i != k) return i < k;
            return j < p;
        }
        return (m < other.m);
    }
}events[4202017];
vector < pair < pair < long long, long >, pair < long long, long > > > S;

int XX = 1, YY = 2;
void update (int pos, point newVal)
{
    if (pos == 1)
    {
        point old = b[pos];
        allSame = 0, b[pos] = newVal;
        for (int i=1; i<=(N + 1) / 2; i++)
            allSame += (b[i].x == b[1].x && b[i].y == b[1].y);
        b[pos] = old;
    }
    else
    allSame -= (b[pos].x == b[1].x && b[pos].y == b[1].y), allSame += (newVal.x == b[1].x && newVal.y == b[1].y);

    if (pos == XX || pos == YY)
    {
        b[pos] = newVal, currCnt = 0, XX = 1, YY = 1;
        for (int i=2; i<=(N + 1) / 2; i++)
            if (b[i].x != b[1].x || b[i].y != b[1].y)
                YY = i;
        for (int i=1; i<=(N + 1) / 2; i++)
            currCnt += det (b[XX], b[YY], b[i]);
    }
    else
    {
        currCnt -= det (b[XX], b[YY], b[pos]), currCnt += det (b[XX], b[YY], newVal);
        b[pos] = newVal;
    }
}

void refresh (int i)
{
    if (i > N + 1 - i) i = N + 1 - i;
    update (i, A[i] + A[N + 1 - i]);
}

long long gcd (long long a, long long b)
{
    long long r;
    while (b != 0)
        r = a % b, a = b, b = r;
    return a;
}

void tryToAdd ()
{
    if (allSame == (N + 1) / 2)
    {
        printf ("-1\n");
        exit (0);
    }
    if (currCnt == (N + 1) / 2)
    {
        int a1 = b[XX].x, b1 = b[XX].y, a2 = b[YY].x, b2 = b[YY].y;
        //printf ("%d %d %d %d\n", a1, b1, a2, b2);
        if (a1 != a2)
        {
            long long x = 1LL * a1 * b2 - 1LL * a2 * b1, y = a1 - a2, d = gcd (x, y), z = b1 - b2, t = a1 - a2, d2 = gcd (z, t);
            //S.insert (unghi (1LL * a2 * b1 - 1LL * a1 * b2, b1 - b2));
            x /= d, y /= d, z /= d2, t /= d2;
            if (y < 0) y = -y, x = -x;
            if (t < 0) z = -z, t = -t;
            S.push_back ({{x, y}, {z, t}});
        }
        else S.push_back ({{0, 0}, {0, 0}});
    }
}

int main()
{
//freopen ("input", "r", stdin);
//freopen ("output", "w", stdout);

scanf ("%d", &N);
if (N <= 2)
{
    printf ("-1\n");
    return 0;
}
for (int i=1; i<=N; i++)
    scanf ("%d %d", &A[i].x, &A[i].y), inv[i] = i;
sort (A + 1, A + N + 1);

for (int i=1; i<=N; i++)
    for (int j=i+1; j<=N; j++)
    {
        nr ++;
        X[nr] = i;
        Y[nr] = j;
        events[nr].where = nr;
        events[nr].m = unghi (A[j].y - A[i].y, A[j].x - A[i].x);
    }
sort (events + 1, events + nr + 1);

for (int i=1; i<=(N + 1) / 2; i++)
    b[i] = A[i] + A[N + 1 - i];
update (1, b[1]), tryToAdd ();
for (int currstp=1; currstp<=nr; currstp++)
{
    int stp = (currstp <= nr ? currstp : currstp - nr);
    int x = X[events[stp].where], y = Y[events[stp].where];
    swap (A[inv[x]], A[inv[y]]);
    swap (inv[x], inv[y]);
//    printf ("%d %d\n", inv[x], inv[y]);
    refresh (inv[x]), refresh (inv[y]);
    tryToAdd ();
}
sort (S.begin (), S.end ());
S.erase (unique (S.begin (), S.end ()), S.end ());
printf ("%d\n", S.size ());

return 0;
}


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

using point = complex<long double>;
#define X real()
#define Y imag()

long double dot(point a, point b) {
  return a.X * b.X + a.Y * b.Y;
}

long double cross(point a, point b) {
  return a.X * b.Y - a.Y * b.X;
}

const long double E = 1e-12;
const int N = 2'000;

point points[N];
long double dist[N];
bool dead[N];

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);

  int n;
  cin >> n;

  point center;
  for (int i = 0; i < n; ++i) {
    int x, y;
    cin >> x >> y;
    points[i] = point(x, y);
    center += points[i];
  }
  center /= n;

  for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
      if (!dead[i] && !dead[j]) {
        point u = 2.0L * center - points[i] - points[j];
        if (abs(u) <= E) {
          dead[i] = true;
          dead[j] = true;
        }
      }
    }
  }

  int m = count(dead, dead + n, false);
  if (m == 0) {
    cout << -1 << "\n";
    exit(0);
  }

  int pivot = 0;
  while (dead[pivot]) {
    ++pivot;
  }

  vector<point> angles;
  for (int i = 0; i < n; ++i) {
    if (!dead[i] && (i != pivot || m % 2 == 1)) {
      point vec = 2.0L * center - points[i] - points[pivot];

      bool ok = true;
      for (auto j : angles) {
        ok &= (abs(cross(vec, j)) > E);
      }

      for (int i = 0; i < n; ++i) {
        dist[i] = cross(vec, points[i]);
      }
      sort(dist, dist + n);

      for (int i = 0; i < n; ++i) {
        ok &= (abs(dist[i] + dist[n - 1 - i] - 2.0L * cross(vec, center)) <= E);
      }

      if (ok) {
        angles.push_back(vec);
      }
    }
  }

  cout << angles.size() << "\n";
}


#include <bits/stdc++.h>

typedef long long ll;
typedef long long llong;
typedef long double ld;
typedef unsigned long long ull;

using namespace std;
const ld eps = 1e-9;

/*
ll pw(ll a, ll b) {
	ll ans = 1; while (b) {
		while (!(b & 1)) b >>= 1, a = (a * a) % MOD;
		ans = (ans * a) % MOD, --b;
	} return ans;
}
*/

struct point {
	ld x, y;
	point(ld X = 0, ld Y = 0) {
		x = X, y = Y;
	}
	point operator+(point a) {
		return point(x + a.x, y + a.y);
	}
	point operator-(point a) {
		return point(x - a.x, y - a.y);
	}
	ld operator*(point a) {
		return x * a.y - y * a.x;
	}
	point operator*(ld k) {
		return point(x * k, y * k);
	}
	ld len() {
		return sqrt(x * x + y * y);
	}
};

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

point norm(point a) {
	ld r = a.len();
	a.x /= r;
	a.y /= r;
	return a;
}

int n;
point p[2100];
int en[2100];
vector<ld> v1;
vector<ld> v2;
vector<point> ans;

int main() {
	point sum = 0;
	cin >> n;
	for (int i = 0; i < n; ++i) {
		cin >> p[i].x >> p[i].y;
		sum = sum + p[i];
	}
	for (int i = 0; i < n; ++i) {
		for (int j = i; j < n; ++j) {
			point xx = p[i] + p[j];
			if (xx * n == sum * 2) {
				en[i] = 1;
				en[j] = 1;
			}
		}
	}
	int st = -1;
	for (int i = 0; i < n; ++i) {
		if (!en[i]) {
			st = i;
			break;
		}
	}
	if (st == -1) {
		cout << -1 << "\n";
		return 0;
	}
	sum.x /= n;
	sum.y /= n;
	for (int i = 0; i < n; ++i)
		p[i] = p[i] - sum;
	for (int i = 0; i < n; ++i) {
		point xx = norm(p[i] + p[st]);
		v1.clear();
		v2.clear();
		for (int j = 0; j < n; ++j) {
			ld cc = (p[j] * xx);
			if (abs(cc) > eps) {
				if (cc > 0)
					v1.push_back(cc);
				else
					v2.push_back(-cc);
			}
		}
		sort(v1.begin(), v1.end());
		sort(v2.begin(), v2.end());
		if (v1.size() != v2.size())
			continue;
		int fl = 0;
		for (int j = 0; j < v1.size(); ++j) {
			if (abs(v1[j] - v2[j]) >= eps) {
				fl = 1;
				break;
			}
		}
		if (fl) {
			continue;
		}
		ans.push_back(xx);
	}
	int cnt = 0;
	for (int i = 0; i < ans.size(); ++i) {
		int fl = 0;
		for (int j = 0; j < i; ++j) {
			if ((ans[i] - ans[j]).len() <= eps || (ans[i] + ans[j]).len() <= eps) {
				fl = 1;
				break;
			}
		}
		if (!fl)
			++cnt;
	}
	cout << cnt << "\n";
	return 0;
}


#include <bits/stdc++.h>
using ll = long long;
using ld = long double;
using namespace std;

const int MAXN = 20001;

int n;
ll x[MAXN], y[MAXN];

void rm(int id) {
    for (int i = id; i + 1 < n; ++i) {
        x[i] = x[i + 1];
        y[i] = y[i + 1];
    }
    --n;
}

ll vals[MAXN];
int ans = 0;

const int BTS = 20;
const ll MSK = (1 << BTS) - 1;

pair<ll, ll> mul(ll x, ll y) {
    bool sgn = false;

    if (x < 0) {
        x = -x;
        sgn = !sgn;
    }

    if (y < 0) {
        y = -y;
        sgn = !sgn;
    }

    ll xl = x & MSK;
    x >>= BTS;
    ll yl = y & MSK;
    y >>= BTS;

    ll lw = (xl * yl);
    ll bg = ((x * y) << BTS) + x * yl + y * xl + (lw >> BTS);
    lw &= MSK;

    if (sgn) {
        bg = -bg;
        lw = -lw;
    }

    return { bg, lw };
}

int origx[MAXN];
int origy[MAXN];
int orign;

void work(ll mdx, ll mdy) {
    bool cool = true;
    for (int j = 0; j < orign; ++j) {
        vals[j] = origx[j] * mdx + origy[j] * mdy;
    }

    sort(vals, vals + orign);

    ll s = vals[0] + vals[orign - 1];

    for (int j = 0; j < orign - 1 - j; ++j) {
        if (vals[j] + vals[orign - 1 - j] != s) {
            cool = false;
            break;
        }
    }

    if (cool) {
        ++ans;
    }
}

ll mdx[MAXN], mdy[MAXN];

int main() {
#ifdef PAUNSVOKNO
    freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false); cout.setf(ios::fixed); cout.precision(20); cout.tie(nullptr); cin.tie(nullptr);

    cin >> n;
    orign = n;

    ll sx = 0, sy = 0;
    for (int i = 0; i < n; ++i) {
        cin >> x[i] >> y[i];
        sx += x[i], sy += y[i];
        origx[i] = x[i], origy[i] = y[i];
    }

    for (int i = 0; i < n; ++i) {
        x[i] = (x[i] * n - sx);
        y[i] = (y[i] * n - sy);
    }

    int cur = 0;
    while (cur < n) {
        if (x[cur] == 0 && y[cur] == 0) {
            rm(cur);
            continue;
        }

        bool ok = true;
        for (int i = cur + 1; i < n; ++i) {
            if (x[i] + x[cur] == 0 && y[i] + y[cur] == 0) {
                rm(i);
                rm(cur);
                ok = false;
                break;
            }
        }

        cur += ok;
    }

    if (n == 0) {
        cout << -1 << "\n";
        return 0;
    }

    mdx[0] = x[0], mdy[0] = y[0];

    work(-y[0], x[0]);

    for (int i = 1; i < n; ++i) {
        bool ok = true;
        mdx[i] = (x[0] + x[i]);
        mdy[i] = (y[0] + y[i]);

        for (int j = 0; j < i; ++j) {
            if (mul(mdx[i], mdy[j]) == mul(mdy[i], mdx[j])) {
                ok = false;
                break;
            }
        }

        if (ok) {
            work(-mdy[i], mdx[i]);
        }
    }

    cout << ans << "\n";
}


//by yjz
#include<bits/stdc++.h>
using namespace std;
#define FF first
#define SS second
#define PB push_back
#define MP make_pair
#define bged(v) (v).begin(),(v).end()
#define foreach(it,s) for(__typeof((s).begin()) it=(s).begin();it!=(s).end();it++)
typedef long long ll;
const int Imx=2147483647;
const ll Lbig=2e18;
const int mod=1e9+7;
//My i/o stream
struct fastio
{
	char s[100000];
	int it,len;
	fastio(){it=len=0;}
	inline char get()
	{
		if(it<len)return s[it++];it=0;
		len=fread(s,1,100000,stdin);
		if(len==0)return EOF;else return s[it++];
	}
	bool notend()
	{
		char c=get();
		while(c==' '||c=='\n')c=get();
		if(it>0)it--;
		return c!=EOF;
	}
}_buff;
#define geti(x) x=getnum()
#define getii(x,y) geti(x),geti(y)
#define getiii(x,y,z) getii(x,y),geti(z)
#define puti(x) putnum(x),putchar(' ')
#define putii(x,y) puti(x),puti(y)
#define putiii(x,y,z) putii(x,y),puti(z)
#define putsi(x) putnum(x),putchar('\n')
#define putsii(x,y) puti(x),putsi(y)
#define putsiii(x,y,z) putii(x,y),putsi(z)
inline ll getnum()
{
	ll r=0;bool ng=0;char c;c=_buff.get();
	while(c!='-'&&(c<'0'||c>'9'))c=_buff.get();
	if(c=='-')ng=1,c=_buff.get();
	while(c>='0'&&c<='9')r=r*10+c-'0',c=_buff.get();
	return ng?-r:r;
}
template<class T> inline void putnum(T x)
{
	if(x<0)putchar('-'),x=-x;
	register short a[20]={},sz=0;
	while(x)a[sz++]=x%10,x/=10;
	if(sz==0)putchar('0');
	for(int i=sz-1;i>=0;i--)putchar('0'+a[i]);
}
inline char getreal(){char c=_buff.get();while(c<=32)c=_buff.get();return c;}
ll n;
pair<ll,ll> a[2111];
ll sumx,sumy;
ll b[2011];
set<pair<ll,ll> >st;
bool check(ll cx,ll p,ll q)//t=p/q
{
	for(int i=1;i<=n;i++)
	{
		b[i]=a[i].FF*cx*q+a[i].SS*p;
	}
	sort(b+1,b+n+1);
	ll M2=b[1]+b[n];
	for(int i=1;i<=n;i++)
	{
		if(b[i]+b[n-i+1]!=M2)return false;
	}
	return true;
}
bool matched[2011];
int mcnt;
void pre_go(int i)
{
	for(int j=i+1;j<=n;j++)
	{
		ll p=n*(-a[i].FF-a[j].FF)+2*sumx;
		ll q=n*(a[i].SS+a[j].SS)-2*sumy;
		if(p==0&&q==0)
		{
			assert(matched[i]==0&&matched[j]==0);
			matched[i]=matched[j]=1;
			mcnt+=2;
		}
	}
}
void go(int i)
{
	if(matched[i])return;
	for(int j=i+1;j<=n;j++)
	{
		ll p=n*(-a[i].FF-a[j].FF)+2*sumx;
		ll q=n*(a[i].SS+a[j].SS)-2*sumy;
//		cerr<<i<<","<<j<<" "<<p<<","<<q<<endl;
		if(q==0&&p!=0)continue;
		assert(!(q==0&&p==0));
		if(check(1,p,q))
		{
			ll g=__gcd(p,q);
			p/=g;
			q/=g;
			if(q<0)q=-q,p=-p;
			st.insert(MP(p,q));
		}
	}
}
int main()
{
	geti(n);
	for(int i=1;i<=n;i++)
	{
		getii(a[i].FF,a[i].SS);
		sumx+=a[i].FF;
		sumy+=a[i].SS;
	}
	for(int i=1;i<=n;i++)pre_go(i);
	if(n-mcnt<=2)
	{
		puts("-1");
		return 0;
	}
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		if(matched[i])continue;
		go(i);
		if((++cnt)>=2)break;
	}
	if(check(0,1,1))st.insert(MP(1,0));
//	foreach(it,st)cerr<<it->FF<<","<<it->SS<<endl;
	cout<<st.size()<<endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <complex>
#include <cstdlib>
#include <algorithm>

using namespace std;

typedef complex<double> point;

double prodvec(point p1,point p2)
{
  return imag(conj(p1)*p2);
}

point leer()
{
  double x,y;
  cin>>x>>y;
  return point(x,y);
}

double error=1e-10;

bool coincide(double x1,double x2)
{
  return abs(x1-x2)<error;
}

bool coincide(point p1,point p2)
{
  return abs(p1-p2)<error;
}

bool compara(point p1,point p2)
{
  if (real(p1)!=real(p2)) return real(p1)<real(p2);
  return imag(p1)<imag(p2);
}

int n;
point vp[2005];
point c;

point get()
{
  for (int i=0;i<n;i++) {
    point q=c+(c-vp[i]);
    bool found=false;
    for (int j=0;j<n and not found;j++)
      found=coincide(q,vp[j]);
    if (not found) return vp[i];
  }
  cout<<-1<<endl;
  exit(0);
  return point(0,0);
}

int main()
{
  cin>>n;
  for (int i=0;i<n;i++)
    vp[i]=leer();
  c=point(0,0);
  for (int i=0;i<n;i++)
    c+=vp[i];
  c/=n;
  point p=get();
  vector<point> vsol;
  for (int cas=0;cas<n;cas++) {
    point q=vp[cas];
    point med=(p+q)/2.0;
    point v=med-c;
    vector<double> vd(n);
    for (int j=0;j<n;j++)
      vd[j]=prodvec(v,vp[j]-c);
    sort(vd.begin(),vd.end());
    bool ok=true;
    for (int i=0,j=n-1;i<=j and ok;i++,j--)
      ok=coincide(vd[i],-vd[j]);
    if (ok)
      vsol.push_back(v);
  }
  int sol=0;
  for (int i=0;i<int(vsol.size());i++) {
    bool ok=true;
    for (int j=0;j<i and ok;j++)
      ok=abs(prodvec(vsol[i],vsol[j]))>error;
    sol+=ok;
  }
  cout<<sol<<endl;
}


//created by missever

#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> P;

const double eps = 1e-8;
const double pi = acos(-1);
inline int sgn(double x) {
    if(x < -eps) return -1;
    else if(x > eps) return 1;
    else return 0;
}
struct Point {
    double x,y;
    Point(double _x = 0.0,double _y = 0.0): x(_x),y(_y) {}
    Point operator + (const Point &b) const {
        return Point(x + b.x,y + b.y);
    }
    Point operator - (const Point &b) const {
        return Point(x - b.x,y - b.y);
    }
    double operator * (const Point &b) const { //点乘
        return (x * b.x + y * b.y);
    }
    double operator ^ (const Point &b) const { //叉乘，判断b点的相对于该点位置关系 左正右负
        return (x * b.y - y * b.x);
    }
    Point operator * (double b) {
        return Point(x * b,y * b);
    }
    bool operator < (const Point &b) const { //水平序比较
        if(sgn(x - b.x) == 0) return sgn(y - b.y) <= 0;
        else return sgn(x - b.x) < 0;
    }
    bool operator == (const Point &b) const {
        return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
    }
    Point rot(double ang) { //旋转，输入角度
        return Point(x * cos(ang) - y * sin(ang),x * sin(ang) + y * cos(ang));
    }
    Point rot(double g1,double g2) { //旋转，输入正弦值，余弦值
        return Point(x * g2 - y * g1,x * g1 + y * g2);
    }
    double norm() { //求模
        return sqrt(x * x + y * y);
    }
    Point unit() { //取单位向量
        double ll = norm();
        return Point(x / ll,y / ll);
    }
};

Point f[2005],p[2005];
bool vis[2005];
double d[2005];

int main() {
#ifdef CX_TEST
    freopen("E:\\program--GG\\test_in.txt", "r", stdin);
#endif
    int n,m,ans = 0,i,j;
    Point o = Point(0,0);
    scanf("%d",&n);
    for(i = 0; i < n; i++) {
        scanf("%lf%lf",&f[i].x,&f[i].y);
        o = o + f[i];
    }
    o = o * (1.0 / n);
    for(i = 0; i < n; i++) {
        if(vis[i]) continue;
        for(j = i; j < n; j++) {
            if(f[i] + f[j] == o * 2.0) {
                vis[i] = vis[j] = 1;
                break;
            }
        }
    }
    for(i = j = 0; i < n; i++) {
        if(!vis[i]) f[j++] = f[i] - o;
    }
    if(!j) return puts("-1"),0;
    n = j;
    for(i = m = 0; i < n; i++) {
        Point u = f[0] + f[i];
        Point v = Point(-u.y,u.x);
        for(j = 0; j < n; j++) d[j] = f[j] * v;
        sort(d,d + n);
        for(j = 0; j < n; j++) if(sgn(d[j] + d[n - 1 - j])) break;
        if(j == n){
            v = v.unit();
            for(j = 0;j < m; j++) if(!sgn(p[j] ^ v)) break;
            if(j == m) {
                ans++;
                p[m++] = v;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef pair <long long, long long> Point;

const int maxN = 2000;
const long long INF = 1000000000000LL;
const Point INFpoint = Point(INF, INF);

Point T[maxN];
vector <Point> proste, rzuty;

long long kw(long long a) {return a*a;}

long double dist(Point& a, Point& b)
{
	return kw(a.first - b.first) + kw(a.second - b.second);
}

Point srodek(Point& a, Point& b)
{
	return Point((a.first + b.first) / 2, (a.second + b.second) / 2);
}

void add(Point& a, Point& b)
{
	a.first += b.first;
	a.second += b.second;
}

void mult(Point& a, long long b)
{
	a.first *= b;
	a.second *= b;
}

int main()
{
	int n;
	scanf ("%d", &n);
	Point mass_cent = Point(0, 0);

	for (int i=0; i<n; i++)
	{
		scanf ("%lld%lld", &T[i].first, &T[i].second);
		add (mass_cent, T[i]);
		mult (T[i], n*2);
	}

	mult(mass_cent, 2);
	Point fix = INFpoint;

	for (int i=0; i<n; i++)
	{
		bool ok = true;

		for (int j=0; j<n; j++)
		{
			if (srodek(T[i], T[j]) == mass_cent)
			{
				ok = false;
				break;
			}
		}

		if (ok)
		{
			fix = T[i];
			break;
		}
	}

	if (fix == INFpoint)
	{
		printf("-1\n");
		return 0;
	}

	for (int i=0; i<n; i++)
	{
		Point s = srodek(fix, T[i]);
		long long a = s.first - mass_cent.first;
		long long b = s.second - mass_cent.second;
		long long c = __gcd(a, b);
		a /= c, b /= c;
		if (a < 0)	a *= -1, b *= -1;
		proste.push_back(make_pair(a, b));
	}

	sort(proste.begin(), proste.end());
	proste.resize(unique(proste.begin(), proste.end()) - proste.begin());
	int res = 0;

	for (int i=0; i<proste.size(); i++)
	{
		long long A = proste[i].first, B = proste[i].second;

		for (int j=0; j<n; j++)
		{
			long long d = B * T[j].first - A * T[j].second;
			rzuty.push_back(make_pair(B * d, (-A) * d));
		}

		sort(rzuty.begin(), rzuty.end());
		bool ok = true;

		for (int j=1; j<=n/2; j++)
		{
			long double d1 = dist(rzuty[j], rzuty[j - 1]);
			int k = rzuty.size() - j;
			long double d2 = dist(rzuty[k], rzuty[k - 1]);
			if (d1 != d2)
			{
				ok = false;
				break;
			}
		}

		if (ok)	res++;
		rzuty.resize(0);
	}

	printf("%d\n", res);
	return 0;
}


/*#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")*/
#include<bits/stdc++.h>
#define ll long long
#define inf 1000000005
#define mod 1000000007
#define put putchar('\n')
#define F(i,a,b) for (int i=(a);i<=(b);i++)
#define D(i,a,b) for (int i=(a);i>=(b);i--)
#define R(i,a,b) for (int i=(a);i<(b);i++)
#define go(i,t) for (int i=head[t];i;i=Next[i])
#define sqr(x) ((x)*(x))
#define re register
#define mp make_pair
#define fi first
#define se second
#define pa pair<int,int>
#define pb push_back
#define be begin()
#define en end()
#define ret return puts("-1"),0;
#define db double
#define N 500055
#define eps 1e-7
//#define int ll
using namespace std;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){char c=getchar();int tot=1;while ((c<'0'|| c>'9')&&c!='-') c=getchar();if (c=='-'){tot=-1;c=getchar();}
int sum=0;while (c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}return sum*tot;}
inline void wr(int x){if (x<0) {putchar('-');wr(-x);return;}if(x>=10)wr(x/10);putchar(x%10+'0');}
inline void wrn(int x){wr(x);put;}inline void wri(int x){wr(x);putchar(' ');}
inline void wrn(int x,int y){wri(x);wrn(y);}inline void wrn(int a,int b,int c){wri(a);wrn(b,c);}
int n,m,ans,vis[N],cnt;
db c[N],q[N];
struct xx{
    int x,y;
}z[N];
db sx,sy,a,b;
signed main(){
    n=read();
    if (n==2) ret;
    F(i,1,n) sx+=z[i].x=read(),sy+=z[i].y=read();
    sx=sx/n,sy=sy/n;
    F(i,1,n){
        if (vis[i]) continue;
        if ((fabs(z[i].x-sx)<eps)&&(fabs(z[i].y-sy)<eps)) vis[i]=1;
        F(j,i+1,n){
            if (vis[j]) continue;
            if ((fabs(z[i].x+z[j].x-sx*2)<eps)&&(fabs(z[i].y+z[j].y-sy*2)<eps)){vis[i]=vis[j]=1;break;}
        }
    }
    int yk=0;
    F(i,1,n) yk+=vis[i];
    if (yk==n) ret;
    random_shuffle(z+1,z+n+1);
    F(ci,1,11){
        swap(z[1],z[ci]);
    F(i,1,n){
        //nx=x+ay
        if (fabs(z[1].y+z[i].y-2*sy)<eps) b=0,a=1;
        else b=1,a=1.0*(2*sx-(z[1].x+z[i].x))/(1.0*(z[1].y+z[i].y-2*sy));
        F(j,1,n) c[j]=a*z[j].y+b*z[j].x;
        sort(c+1,c+n+1);
        db t=c[1]+c[n];
        int pd=1;
        F(j,1,n){
            if (fabs(c[j]+c[n-j+1]-t)>eps) pd=0;
        }
        if (pd) q[++cnt]=(b==0)?-2151.2352:a;
    }
    }
    q[0]=-1241.23462;
    sort(q+1,q+cnt+1);
    F(i,1,cnt){
        if (fabs(q[i]-q[i-1])>eps) ans++;
    }
    wrn(ans);
    return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> PII;

const int MM = 1e9 + 7;
const double eps = 1e-8;
const int MAXN = 2e3 + 10;
const int MAXM = 2e6 + 10;

int n;

struct Pt{
	long long x, y;
};

bool operator < (const Pt & a, const Pt & b){
	if (a.x == b.x)
		return a.y < b.y;
	else
		return a.x < b.x;
}

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

inline long long operator * (const Pt & a, const Pt & b){
	return a.x * b.y - a.y * b.x;
}

inline long long operator % (const Pt & a, const Pt & b){
	return a.x * b.x + a.y * b.y;
}

inline Pt operator - (const Pt & a, const Pt & b){
	return (Pt){a.x - b.x, a.y - b.y};
}

inline Pt operator + (const Pt & a, const Pt & b){
	return (Pt){a.x + b.x, a.y + b.y};
}

inline Pt operator * (const Pt & a, const ll u){
	return (Pt){a.x * u, a.y * u};
}

long long sqr(long long x){
	return x * x;
}

inline double len(const Pt & a){
	return sqrt(sqr(a.x) + sqr(a.y));
}

long long absll(long long x){
	return x < 0 ? -x : x;
}

vector<Pt> convex_hull(vector<Pt> u){
    sort(u.begin(), u.end());
    u.erase(unique(u.begin(), u.end()), u.end());
    if (u.size() < 3)
		return u;
    vector<Pt> c;
    for(int i=0, o=1, m=1; ~i; i += o){
        while(c.size() > m){
            Pt a = c.back() - c[c.size() - 2];
            Pt b = c.back() - u[i];
            if (a * b < 0)
				break; // <= 0 保留共线点
            c.pop_back();
        }
        c.push_back(u[i]);
        if(i + 1 == u.size())
			m = c.size(), o = -1;
    }
    c.pop_back();
    return c;
}

set<PII> PP, LL, PL;

void addpp(int u, int v){
	u %= n, v %= n;
	if (u > v) swap(u, v);
	PP.insert(PII(u, v));
}

void addpl(int u, int v){
}

void addll(int u, int v){
}

void xzkk(vector<Pt>& c){
	auto Area = [&](int u, int v, int w){
		u %= n, v %= n, w %= n;
		return abs((c[u] - c[v]) * (c[w] - c[v]));
	};
	int tmpn = n;
	n = c.size();
	int v = 0, u = 1;
	while(Area(v,v+1,u+1)>
			Area(v,v+1,u))
		u++;
	PP.clear();
	PL.clear();
	LL.clear();
	addpp(v, u);
	addpp(v+1, u);
	addpl(u, v);
	for(int i=0;i<=4*n;i++){
	  addpp(u, v);
	  if (i & 1){
	    if ((c[(v+1)%n]-c[v%n])*
	        (c[(u+1)%n]-c[u%n]) > 0)
		  swap(u, v);
	  }
	  else{
		addpp(u, v+1);
		addpl(u, v);
		if (Area(v, v+1, u)
			==Area(v,v+1,u+1)){
		  addpp(u+1, v);
		  addpp(u+1, v+1);
		  addpl(u+1, v);
		  addpl(v, u);
		  addpl(v+1, u);
		  addll(u, v);
		  u++;
		}
		v++;
	  }
	}
	n = tmpn;
}

ll ans;
vector<Pt> a;

vector<Pt> ret;

void check(Pt dir, Pt&U, Pt&V){
	ll r = __gcd(abs(dir.x), abs(dir.y));
	dir.x /= r, dir.y /= r;
	if (dir.x < 0){
		dir.x = -dir.x;
		dir.y = -dir.y;
	}
	if (dir.x == 0 && dir.y < 0){
		dir.y = -dir.y;
	}
	//vector<__int128> F;
	//__int128 A = dir.x;
	//__int128 B = dir.y;
	vector<ll> F;
	ll A = dir.x, B = dir.y;
	ll UVx = U.x + V.x;
	ll UVy = U.y + V.y;
	ll sm = A * UVx + B * UVy;
	for (auto &p : a){
		F.push_back(A * p.x + B * p.y);
	}
	sort(F.begin(), F.end());
	for (int i = 0; i * 2 < F.size(); i++){
		if (F[i] + F[F.size() - 1 - i] != sm){
			return ;
		}
	}
	ret.push_back(dir);
}

ll nico = 453209;
ll maki = 453757;

void gao(Pt U, Pt V){
	ll sx = 0;
	ll sy = 0;
	ll sxx = 0;
	ll syy = 0;
	ll sxy = 0;
	ll UVx = U.x + V.x + 2 * nico;
	ll UVy = U.y + V.y;
	for (auto &p : a){
		sx += p.x;
		sy += p.y;
		sxx += sqr(p.x + nico) - sqr(UVx - p.x + nico);
		syy += sqr(p.y) - sqr(UVy - p.y);
		sxy += (p.x + nico) * p.y - (UVx - p.x + nico) * (UVy - p.y);
	}
	sx = sx * 2 - n * (U.x + V.x);
	sy = sy * 2 - n * (U.y + V.y);
	/*
	cerr << "+++++++++++++++++++++++++++++" << endl;
	cerr << U.x << ' ' << U.y << ' ' << V.x << ' ' << V.y << endl;
	cerr << sx << ' ' << sy << ' ' << sxx << ' ' << syy << ' ' << sxy << endl;
	*/
	if (sx == 0){
		if (sy != 0)
			check((Pt){1ll, 0ll}, U, V);
		else{
			sxy *= 2;
			if (sxx == 0 && syy == 0){
				ans = 1ll << 60;
			}
			ans = 1ll << 60;
			/*
			else{
				if (sxx != 0){
					__int128 del = (__int128)sxy * sxy - (__int128)4 * sxx * syy;
					ll tmp = sqrt((long double)del);
					while (tmp * tmp < del) tmp++;
					while (tmp * tmp > del) tmp--;
					if (tmp * tmp != del)
						return ;
					check((Pt){-sxy+tmp, 2*sxx}, U, V);
					check((Pt){-sxy-tmp, 2*sxx}, U, V);
				}
				else{
					__int128 del = (__int128)sxy * sxy - (__int128)4 * sxx * syy;
					ll tmp = sqrt((long double)del);
					while (tmp * tmp < del) tmp++;
					while (tmp * tmp > del) tmp--;
					if (tmp * tmp != del)
						return ;
					check((Pt){2*syy, -sxy+tmp}, U, V);
					check((Pt){2*syy, -sxy-tmp}, U, V);
				}
			}
			*/
		}
	}
	else{
		if (sy != 0){
			check((Pt){sy, -sx}, U, V);
		}
		else{
			check((Pt){0ll, 1ll}, U, V);
		}
	}
}

void restore(){
	if (ans >= 1ll << 60)
		return ;
	sort(ret.begin(), ret.end(), [](const Pt & a, const Pt & b){
		if (a.x == b.x) return a.y < b.y;
		else return a.x < b.x;
	});
	ret.erase(unique(ret.begin(), ret.end()), ret.end());
	ans = ret.size();
}

int vis[2222];

void solve(){
	scanf("%d", &n);
	a.resize(n);
	for (int i = 0; i < n; i++)
		scanf("%lld%lld", &a[i].x, &a[i].y);
	Pt O;
	O.x = O.y = 0;
	for (int i = 0; i < n; i++)
		O = O + a[i];
	if (O.x * 2 % n == 0 && O.y * 2 % n == 0){
		O.x = O.x * 2 / n;
		O.y = O.y * 2 / n;
		for (int i = 0; i < n; i++)
			if (a[i] * 2 == O){
				vis[i] = 1;
			}
			else if (!vis[i]){
				for (int j = i + 1; j < n; j++)
					if (!vis[j] && a[i] + a[j] == O){
						vis[i] = 1, vis[j] = 1;
						break;
					}
			}
		vector<Pt> c;
		for (int i = 0; i < n; i++)
			if (!vis[i]){
				c.push_back(a[i]);
			}
		a.swap(c);
		c.clear();
		n = a.size();
	}
	if (n == 0){
		puts("-1");
		return ;
	}
	vector<Pt> b = convex_hull(a);
	xzkk(b);
	ans = 0;
	for (auto &x : PP){
		if (x.first != x.second)
			gao(b[x.first], b[x.second]);
	}
	restore();
	if (ans >= 1ll << 60){
		puts("-1");
	}
	else
		printf("%lld\n", ans);
}

int main(){
	solve();
	return 0;
}


#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
typedef long long LL;
const int _=1e2;
const int maxn=2e3+_;
inline LL gcd(LL x,LL y){return x==0?y:gcd(y%x,x);}

struct point{LL x,y;}p[maxn]; bool dl[maxn];
LL mul(point p1,point p2){return p1.x*p2.x+p1.y*p2.y;}
int len;LL d[maxn];
map<pair<LL,LL>,bool>mp;
bool check(point p)
{
	if(p.x!=0&&p.y!=0)
	{
		LL g=gcd(p.x,p.y);
		p.x/=g,p.y/=g;
	}
	if(p.x<0)p.x=-p.x,p.y=-p.y;
	if(p.x==0)p.y=1;
	if(p.y==0)p.x=1;
	if(mp.count(make_pair(p.x,p.y)))return true;
	else {mp[make_pair(p.x,p.y)]=true;return false;}
}
int main()
{
	int n,sumx=0,sumy=0;
	scanf("%d",&n);
	if(n==1){puts("-1");return 0;}
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&p[i].x,&p[i].y);
		sumx+=p[i].x;
		sumy+=p[i].y;
		p[i].x*=n,p[i].y*=n;
	}
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++)
			if(p[i].x+p[j].x==2*sumx&&p[i].y+p[j].y==2*sumy)
				dl[i]=dl[j]=true;
	int tp=0;
	for(int i=1;i<=n;i++)
		if(!dl[i])p[++tp]=p[i],p[tp].x-=sumx,p[tp].y-=sumy;
	n=tp;
	if(n==0){puts("-1");return 0;}

	int ans=0;
	for(int i=1;i<=n;i++)
	{
		point u={p[1].y+p[i].y,-p[1].x-p[i].x};
		if(check(u))continue;
		len=0;
		for(int j=1;j<=n;j++)
			d[++len]=mul(u,p[j]);
		sort(d+1,d+len+1);
		bool bk=false;
		for(int j=1;j<=(n+1)/2;j++)
			if(d[1]+d[n]!=d[j]+d[n-j+1]){bk=true;break;}
		if(!bk)ans++;
	}
	printf("%d\n",ans);

	return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 2002;
const double EPS = 1e-7;
double d[N];
int vis[N];

struct Point {
    double x, y;
    Point(){}
    Point(double x_, double y_) {
        x = x_;
        y = y_;
    }
    void read() {
        scanf("%lf %lf", &x, &y);
    }
    void print() {
        printf("%.5f %.5f\n", x, y);
    }
    Point operator + (const Point &other) const {
        return Point(x+other.x, y+other.y);
    }
    Point operator - (const Point &other) const {
        return Point(x-other.x, y-other.y);
    }
    Point operator / (const double &val) const {
        return Point(x/val, y/val);
    }
    double operator * (const Point &other) const{
        return x*other.x + y*other.y;
    }
    double operator ^ (const Point &other) const {
        return x * other.y - y * other.x;
    }

} p[N];

struct Line
{
    Point start, direct;
    Line() {}
    Line(Point start_, Point direct_) {
        start = start_;
        direct = direct_;
    }
    double dis(Point P) {
        return (direct ^ (P - start)) / sqrt(direct * direct);
    }
    bool same(Line L) {
        if (abs(direct ^ L.direct) > EPS) return 0;
        if (abs(direct ^ (L.start - start)) > EPS) return 0;
        return 1;
    }
} l[N]; int cnt = 0;

int n;
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i ++)
        p[i].read();

    if (n <= 2) {
        printf("-1\n"); return 0;
    }

    if (p[1]*p[1] < EPS)
        swap(p[1], p[2]);

    Point M(0, 0);
    for (int i = 1; i <= n; i ++)
        M = M + p[i];
    M = M / n;

    //M.print();

    int sym = 0, pos;
    for (int i = 1; i <= n; i ++) {
        int flag = 0;
        for (int j = 1; j <= n; j ++) {
            if ((p[j]+p[i])*(p[j]+p[i])<EPS || ((p[j]+p[i])/2-M)*((p[j]+p[i])/2-M)<EPS)
                flag = 1;
        }
        if (flag) sym ++;
        else pos = i;
    }

    if (sym == n) {
        printf("%d\n", -1);
        return 0;
    }

    swap(p[1], p[pos]);

    for (int i = 1; i <= n; i ++) {
        if ((p[1]+p[i])*(p[1]+p[i])<EPS)
            continue;

        if (((p[1]+p[i])/2-M)*((p[1]+p[i])/2-M)<EPS)
            continue;

        Point P = (p[1] + p[i]) / 2;
        Line L = Line(P, P - M);
        for (int j = 1; j <= n; j ++) {
            d[j] = L.dis(p[j]);
        }

        sort(d+1, d+1+n);
        /*
        printf("%d\n", i);
        for (int i = 1; i <= n; i ++) {
            printf("%.5f ", d[i]);
        }
        printf("\n");
        */
        bool ok = 1;
        for (int i = 1; i <= n; i ++) {
            if (d[i] + d[n+1-i] > EPS) {
                ok = 0; break;
            }
        }
        if (ok) l[++cnt] = L;
    }

    //printf("%d\n", cnt);
    int ans = 0;
    for (int i = 1; i <= cnt; i ++) {
        int flag = 1;
        for (int j = 1; j < i; j ++) {
            if (l[i].same(l[j])) flag = 0;
        }
        if (flag) ans ++;
    }
    printf("%d\n", ans);

}


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

#define error(args...) { vector<string> _v = split(#args, ','); err(_v.begin(), args); }
vector<string> split(const string& s, char c) { vector<string> v; stringstream ss(s); string x; while (getline(ss, x, c)) v.push_back(move(x)); return v; }
void err(vector<string>::iterator it) {}
template<typename T, typename... Args> void err(vector<string>::iterator it, T a, Args... args) { cerr << it->substr((*it)[0] == ' ', it->length()) << " = " << a << '\n'; err(++it, args...); }

#define MAXN 2013
#define MOD 1000000007
typedef long long LL;
int N;
LL X[MAXN], Y[MAXN];
LL MX, MY;
set<pair<LL, LL> > s1;
unordered_multiset<LL> s;
set<pair<LL, LL> > slopes;

bool go(int p, int q) {
	// pair point 0 with point p
	LL nx = X[q] + X[p]; // norm vectors
	LL ny = Y[q] + Y[p];
	LL g = __gcd(nx, ny);
	nx /= g;
	ny /= g;
	if (nx < 0 || (nx == 0 && ny < 0)) {
		nx = -nx;
		ny = -ny;
	}
	pair<LL, LL> pp = {nx, ny};
	if (slopes.count(pp)) return false;
	slopes.insert(pp);

	s.clear();
	for (int i = 0; i < N; i++) {
		LL h = ny * X[i] - nx * Y[i];
		auto it = s.find(-h);
		if (it != s.end()) {
			s.erase(it);
		}
		else {
			s.insert(h);
		}
	}
	return s.size() <= 1;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	// freopen("input.txt", "r", stdin);

	cin >> N;
	for (int i = 0; i < N; i++) {
		cin >> X[i] >> Y[i];
		MX += X[i];
		MY += Y[i];
		X[i] *= N;
		Y[i] *= N;
	}

	// Step 1: Normalization
	for (int i = 0; i < N; i++) {
		X[i] -= MX;
		Y[i] -= MY;
	}

	// Step 2: Removal of "useless" points
	for (int i = 0; i < N; i++) {
		pair<LL, LL> np = {-X[i], -Y[i]};
		if (s1.count(np)) {
			s1.erase(np);
		}
		else {
			s1.insert(make_pair(X[i], Y[i]));
		}
	}

	N = 0;
	for (pair<LL, LL> p : s1) {
		X[N] = p.first, Y[N]=p.second;
		N++;
	}

	if (N <= 1) {
		cout << -1 << endl;
		return 0;
	}

	// Step 3: Try pairing 0 with every point p
	int ans = 0;
	for (int p = 0; p < N; p++) {
		if (go(0, p)) {
			++ans;
		}
	}

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


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

const int N = 2005;

#define double long double

const double ep = 1e-10;

struct pnt {
	double x, y;
    pnt() {x = y = 0;}
    pnt(double xx, double yy) {x = xx, y = yy;}
    pnt operator + (pnt a) {return pnt(x + a.x, y + a.y);}
    void in() {int xx, yy; cin >> xx >> yy; x = xx, y = yy;}
    double operator ^ (const pnt &a) const {return x*a.y-y*a.x;}
    bool operator < (const pnt &a) const {return x != a.x ? x < a.x : y < a.y;}
    bool int_pnt(pnt &a) {
        int xx = x + (x > 0 ? 0.5 : -0.5), yy = y + (y > 0 ? 0.5 : -0.5);
        if (abs(x-xx) < ep && abs(y-yy) < ep) {
            a = pnt(xx, yy);
            return 1;
        }
        return 0;
    }
} p[N], M, MM;

vector <pnt> P;

int n;

map <pnt, int> h;

bool opp[N];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i ++) {
		p[i].in();
		M = M + p[i];
        h[p[i]] = i;
    }
    M.x /= n, M.y /= n;
    MM.x = M.x * 2, MM.y = M.y * 2;
    for (int i = 1; i <= n; i ++) if (!opp[i]) {
        pnt pp = pnt(MM.x-p[i].x, MM.y-p[i].y), qq;
        if (pp.int_pnt(qq) && h.count(qq)) {
            int t = h[qq];
            opp[t] = 1; opp[i] = 1;
        }
    }
    for (int i = 1; i <= n; i ++) if (!opp[i]) P.push_back(p[i]);
    if (P.empty()) puts("-1");
    else {
        pnt A = P[0];
        int ans = 0;
        vector <pnt> D;
        for (auto x : P) {
            pnt AM = A + x;
            AM.x /= 2, AM.y /= 2;
            pnt d = pnt(M.x - AM.x, M.y - AM.y);
            vector <double> pos, neg;
            for (auto y : P) {
                double l = d ^ pnt(y.x - AM.x, y.y - AM.y);
                if (abs(l) < ep) continue;
                if (l < 0) neg.push_back(-l);
                else pos.push_back(l);

            }
            if (neg.size() != pos.size()) continue;
            sort(neg.begin(), neg.end());
            sort(pos.begin(), pos.end());
            bool flag = 0;
            for (int i = 0; i < pos.size(); i ++) if (abs(pos[i]-neg[i]) > ep) flag = 1;
            if (!flag) D.push_back(d);
        }
        for (auto &x : D) {
            if (x.y < 0) x.y = -x.y, x.x = -x.x;
            if (x.y == 0 && x.x < 0) x.x = -x.x;
        }
        sort(D.begin(), D.end(), [](const pnt &x, const pnt &y) {
            return (x^y) > 0;
		});
        int sz = D.size();
        for (int i = 0, j; i < sz; i = j) {
            for (j = i; j < sz && (D[i]^D[j])==0; j ++);
            ans ++;
        }
        printf("%d\n", ans);
    }
	return 0;
}

                        //hello


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

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

template <class T>
struct Point {
    typedef Point P;
    T x, y;
    explicit Point(T x=0, T y=0) : x(x), y(y) {}
    bool operator<(P p) const { return tie(x,y) < tie(p.x,p.y); }
    bool operator==(P p) const { return tie(x,y)==tie(p.x,p.y); }
    P operator+(P p) const { return P(x+p.x, y+p.y); }
    P operator-(P p) const { return P(x-p.x, y-p.y); }
    P operator*(T d) const { return P(x*d, y*d); }
    P operator/(T d) const { return P(x/d, y/d); }
    T dot(P p) const { return x*p.x + y*p.y; }
    T cross(P p) const { return x*p.y - y*p.x; }
    T cross(P a, P b) const { return (a-*this).cross(b-*this); }
    T dist2() const { return x*x + y*y; }
    double dist() const { return sqrt((double)dist2()); }
    // angle to x-axis in interval [-pi, pi]
    double angle() const { return atan2(y, x); }
    P unit() const { return *this/dist(); } // makes dist()=1
    P perp() const { return P(-y, x); } // rotates +90 degrees
    P normal() const { return perp().unit(); }
    // returns point rotated 'a' radians ccw around the origin
    P rotate(double a) const {
        return P(x*cos(a)-y*sin(a),x*sin(a)+y*cos(a)); }
};

typedef Point<ll> P;
pair<vi, vi> ulHull(const vector<P>& S) {
    vi Q(sz(S)), U, L;
    iota(all(Q), 0);
    sort(all(Q), [&S](int a, int b){ return S[a] < S[b]; });
    trav(it, Q) {
#define ADDP(C, cmp) while (sz(C) > 1 && S[C[sz(C)-2]].cross(\
    S[it], S[C.back()]) cmp 0) C.pop_back(); C.push_back(it);
        ADDP(U, <=); ADDP(L, >=);
    }
    return {U, L};
}

vi convexHull(const vector<P>& S) {
    vi u, l; tie(u, l) = ulHull(S);
    if (sz(S) <= 1) return u;
    if (S[u[0]] == S[u[1]]) return {0};
    l.insert(l.end(), u.rbegin()+1, u.rend()-1);
    return l;
}

pair<LL,LL> neg(pair<LL,LL> d){
    return make_pair(-d.first, -d.second);
}

typedef Point<LL> P;
int main(){
    LL n;
    cin >> n;
    pair<LL,LL> a[n];
    pair<LL,LL> sum = make_pair(0,0);
    for(int i = 0; i < n; i++){
        cin >> a[i].first >> a[i].second;
        sum.first += a[i].first;
        sum.second += a[i].second;
        a[i].first *= n;
        a[i].second *= n;
    }
    map<pair<LL,LL>, LL> g;
    for(int i = 0; i < n; i++){
        a[i].first -= sum.first;
        a[i].second -= sum.second;
        g[a[i]]++;
        //cout << a[i].first << " " << a[i].second << endl;
    }
    for(int i = 0; i < n; i++){
        if(g[a[i]] > 0 && g[neg(a[i])] > 0){
            g.erase(a[i]);
            g.erase(neg(a[i]));
        }
    }
    g.erase(make_pair(0,0));
    vector<pair<LL,LL> > pts;
    for(map<pair<LL,LL>, LL>::iterator it = g.begin(); it != g.end(); it++){
        if(it->second <= 0) continue;
        pts.push_back(it->first);
    }
    if(pts.size() == 0){
        cout << -1 << endl;
        return 0;
    }
    vector<P> z;
    for(int i = 0; i < pts.size(); i++){
        z.push_back(P(pts[i].first, pts[i].second));
        //cout << z[i].x << " " << z[i].y << endl;
    }

    vector<int> hull = convexHull(z);

    vector<P> checks;
    for(int j = 0; j < hull.size(); j++){
        int nj = (j+1) % (hull.size());
        P diff = z[hull[nj]] - z[hull[j]];
        LL maxcross = 0;
        LL mincross = 0;
        for(int c = 0; c < z.size(); c++){
            maxcross = max(maxcross, diff.cross(z[c]));
            mincross = min(mincross, diff.cross(z[c]));
        }
        vector<int> maxs;
        vector<int> mins;
        for(int c = 0; c < hull.size(); c++){
            if(diff.cross(z[hull[c]]) == maxcross) maxs.push_back(hull[c]);
            if(diff.cross(z[hull[c]]) == mincross) mins.push_back(hull[c]);
        }
        for(int b = 0; b < maxs.size(); b++){
            for(int a = 0; a < mins.size(); a++){
                if(maxs[b] == mins[a]) continue;
                P del = z[maxs[b]] + z[mins[a]];
                LL gg = __gcd(del.x, del.y);
                del.x /= gg; del.y /= gg;
                if(del.x < 0 || (del.x == 0 && del.y < 0)){
                    del.x *= -1;
                    del.y *= -1;
                }
                checks.push_back(del);
            }
        }
    }
    map<pair<LL,LL>, int> fans;
    for(int j = 0; j < checks.size(); j++){
        map<LL,int> freq;
        for(int i = 0; i < z.size(); i++){
            freq[z[i].cross(checks[j])]++;
        }
        LL ok = 1;
        for(int i = 0; i < z.size(); i++){
            LL cur = z[i].cross(checks[j]);
            if(freq[cur] != freq[-cur]) ok = 0;
        }
        if(ok){
            fans[make_pair(checks[j].x, checks[j].y) ] = 1;
        }
    }
    cout << fans.size() << endl;
}


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

typedef double lf;
typedef pair<int, int> pii;
typedef pair<lf, lf> pdd;

const int MN = 2010;

int N;
pii P[MN];
pdd C;
vector<pii> tmp;
int chk[MN];

struct Line {
    lf a, b, c;
    lf f(lf x, lf y) {
        return a * x + b * y + c;
    }
};

Line getLine(pdd p, pdd q) {
    return { (q.second - p.second), (p.first - q.first), (q.first - p.first) * p.second - (q.second - p.second) * p.first };
}

vector<lf> slope;

int main() {
    scanf("%d", &N);

    lf xsum = 0;
    lf ysum = 0;
    for(int i = 0; i < N; i++) {
        scanf("%d %d", &P[i].first, &P[i].second);
        xsum += P[i].first;
        ysum += P[i].second;
    }

    C = { xsum / N, ysum / N };

    for(int i = 0; i < N; i++) {
        for(int j = i; j < N; j++) {
            if(abs(2 * C.first - P[i].first - P[j].first) < 1e-9 && abs(2 * C.second - P[i].second - P[j].second) < 1e-9) {
                chk[i] = 1;
                chk[j] = 1;
                break;
            }
        }
    }

    for(int i = 0; i < N; i++) if(!chk[i]) tmp.push_back(P[i]);
    N = tmp.size();
    for(int i = 0; i < N; i++) P[i] = tmp[i];
    if(!N) {
        printf("-1");
        return 0;
    }

    for(int i = (N % 2? 0 : 1); i < N; i++) {
        pdd M = { (lf)(P[0].first + P[i].first) / 2, (lf)(P[0].second + P[i].second) / 2 };
        Line line = getLine(C, M);

        vector<lf> tmp;
        for(int j = 0; j < N; j++) {
            tmp.push_back(line.f(P[j].first, P[j].second));
        }
        sort(tmp.begin(), tmp.end());

        bool ok = true;
        for(int j = 0; j < N; j++) if(abs(tmp[j] + tmp[N - 1 - j]) > 1e-9) {
            ok = false;
            break;
        }
        if(ok) {
            if(line.a == 0) slope.push_back(1e9);
            else slope.push_back(line.b / line.a);
        }
    }

    sort(slope.begin(), slope.end());
    int ans = 0;
    for(int i = 0; i < slope.size(); i++) {
        if(i == 0 || abs(slope[i] - slope[i - 1]) > 1e-9) ans++;
    }

    printf("%d", ans);
}


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <map>
#include <set>

using namespace std;

using ll = long long;
#define range(i,a,b) for(auto i=(a);i<(b);i++)
#define rep(i,n) range(i,0,n)
#define fst first
#define snd second

template <typename T>
struct Point {
T x, y;
inline Point & operator+=(const Point & o) { x += o.x, y += o.y; return *this; }
inline Point operator+(const Point & o) const { auto p = *this; return p += o; }
inline Point & operator-=(const Point & o) { x -= o.x, y -= o.y; return *this; }
inline Point operator-(const Point & o) const { auto p = *this; return p -= o; }
inline T operator*(const Point & o) { return x * o.x + y * o.y; }
inline T operator%(const Point & o) const { return x * o.y - y * o.x; }
inline bool operator==(const Point & o) const { return x == o.x && y == o.y; }
inline bool operator<(const Point & o) const { return x < o.x || (x == o.x && y < o.y); }
inline double r() const { return hypot(x, y); }
inline T q() const { return atan2(y, x); }
};
template <typename T> inline Point<T> operator*(T c, Point<T> a) { return {c * a.x, c * a.y}; }
template <typename T> inline Point<T> operator-(Point<T> a) { return (T) -1 * a; }

constexpr int N = 2005;

Point<ll> pts[N];

bool symmetric(Point<ll> * p0, Point<ll> * p1, Point<ll> & l) {
	map<ll, int> proj;
	range (pt, p0, p1) {
		ll d = *pt % l;
		if (d > 0) proj[d]++;
		else if (d < 0) proj[-d]--;
	}
	for (auto & p : proj) if (p.snd) return false;
	return true;
}

int work() {
	int n;
	scanf("%d", &n);

	Point<ll> ctr {0, 0};
	rep (i, n) {
		scanf("%lld%lld", &pts[i].x, &pts[i].y);
		ctr += pts[i];
	}

	set<Point<ll>> mirror;
	rep (i, n) {
		pts[i] = (ll) n * pts[i] - ctr;
		if (!mirror.erase(-pts[i])) mirror.insert(pts[i]);
	}

	n = 0;
	for (auto & pt : mirror) pts[n++] = pt;
	if (n < 2) return -1;

	int ans = 0;
	set<Point<ll>> ls;
	rep (i, n) {
		Point<ll> l = pts[0] + pts[i];
		ll g = __gcd(abs(l.x), abs(l.y)) * (Point<ll>{0, 0} < l ? 1 : -1);
		l.x /= g, l.y /= g;
		if (ls.count(l)) continue;
		ls.insert(l);
		ans += symmetric(pts, pts + n, l);
	}
	return ans;
}

int main() {
	printf("%d\n", work());
	return 0;
}


#include <iostream>
#include <vector>
#include <cmath>
#include <map>
#include <algorithm>
#include <cassert>
#define MAXN 2005
#define eps 1e-8
using namespace std;

const double PI = acos(-1);

struct Point {
    double x, y;

    Point(): x(0), y(0) {}
    Point(double x, double y): x(x), y(y) {}

    friend Point operator+(const Point &A, const Point &B);
    friend Point operator/(const Point &A, double k);
};

Point operator+(const Point &A, const Point &B) {
    return Point(A.x + B.x, A.y + B.y);
}

Point operator/(const Point &A, double k) {
    return Point(A.x / k, A.y / k);
}

int n;
Point p[MAXN], mass;
bool erased[MAXN];
vector<Point> vp;

bool equal(double x, double y) {
    return fabs(x - y) < eps;
}

struct Comp {
    bool operator()(double a, double b) {
        if (equal(a, b))
            return 0;
        return a < b;
    }
};

map<double, int, Comp> posLines;

Point getVector(const Point &A, const Point &B) {
    Point v(A.x - B.x, A.y - B.y);

    if (v.y < 0)
        v.x = -v.x, v.y = -v.y;

    return v;
}

Point getPerpendicularVector(const Point &v) {
    Point pv(-v.y, v.x);

    if (pv.y < 0)
        pv.x = -pv.x, pv.y = -pv.y;

    return pv;
}

Point rotate(const Point &P, double alfa) {
    double c = cos(alfa);
    double s = sin(alfa);

    return Point(c * P.x + s * P.y, -s * P.x + c * P.y);
}

bool check(double alfa) {
    vector<double> v;

    for (auto &P: vp)
        v.push_back(rotate(P, alfa).x);

    double massx = rotate(mass, alfa).x;

    sort(v.begin(), v.end());
    for (int i = 0, j = n - 1; i <= j; ++i, --j) {
        if (!equal(massx, (v[i] + v[j]) / 2))
            return 0;
    }

    return 1;
}

int main() {
    ios::sync_with_stdio(0);

    cin >> n;

    for (int i = 1; i <= n; ++i) {
        cin >> p[i].x >> p[i].y;
        mass = mass + p[i];
    }

    mass = mass / n;

    for (int i = 1; i <= n; ++i) {
        if (equal(p[i].x, mass.x) && equal(p[i].y, mass.y))
            erased[i] = 1;
        if (erased[i])
            continue;
        for (int j = i + 1; j <= n; ++j) {
            Point M = (p[i] + p[j]) / 2;

            if (equal(M.x, mass.x) && equal(M.y, mass.y))
                erased[i] = erased[j] = 1;
        }
    }

    for (int i = 1; i <= n; ++i) {
        if (!erased[i]) {
            vp.push_back(p[i]);
        }
    }

    if (vp.empty()) {
        cout << "-1\n";
        return 0;
    }

    n = (int) vp.size();

    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            Point M = (vp[i] + vp[j]) / 2;
            Point v = getPerpendicularVector(getVector(mass, M));

            double alfa = atan2(v.y, v.x);
            assert(alfa < -PI + eps || (alfa > -eps && alfa < PI + eps));
            if (alfa < -PI + eps)
                alfa = PI;

            ++posLines[alfa];
        }
    }

    int ans = 0;
    for (auto &entry: posLines) {
        if (entry.second >= n / 2) {
            ans += check(entry.first);
        }
    }

    cout << ans << "\n";

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 105;
typedef long long ll;

ll f[maxn >> 1];
ll cal(char c, int num) {
//	printf("%c %d\n", c, num);
	if(c == 'A') return (num & 1) ? f[(num >> 1) + 1] : f[(num >> 1) - 1];
	else return (num & 1) ? f[(num >> 1) + 1] : f[(num >> 1) + 2];
}
int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	f[0] = 0, f[1] = 1;
	for(int i = 2; i < (maxn >> 1); i++) f[i] = f[i - 1] + f[i - 2];
	string s;
	cin >> s;
	int n = s.length();
	vector<int> v;
	for(int i = 0; i < n; i++)
		if(s[i] == s[(i - 1 + n) % n]) v.push_back(i);
	if(v.empty()) return 0 * printf("%lld\n", f[(n >> 1) - 1] + f[(n >> 1) + 1]);
	ll ans = 1;
	v.push_back(v[0] + n);
	int sz = (int)v.size();
	for(int i = 0; i < sz - 1; i++) ans *= cal(s[v[i]], v[i + 1] - v[i]);
	printf("%lld\n", ans);
	return 0;
}


#include <iostream>
#include <vector>
#define int long long
#define endl '\n'

using namespace std;

int a1[1000000+5];
vector <vector <int> > g;
bool used[1000000+5];
int timer, tin[1000000+5], fup[1000000+5];

vector <int> ans;

void dfs (int v, int p = -1) {
	used[v] = true;
	tin[v] = fup[v] = timer++;
	int children = 0;
	for (size_t i=0; i<g[v].size(); ++i) {
		int to = g[v][i];
		if (to == p)  continue;
		if (used[to])
			fup[v] = min (fup[v], tin[to]);
		else {
			dfs (to, v);
			fup[v] = min (fup[v], fup[to]);
			if (fup[to] >= tin[v] && p != -1)
				ans.push_back(v);
			++children;
		}
	}
	if (p == -1 && children > 1)
		ans.push_back(v);
}

void check(int v, int q, int t)
{
    used[v]=1;
    if (v==q) return;
    a1[v] += t;
    for (auto i:g[v])
    {
        if (!used[i]) check(i,q,t);
    }

}

int32_t main() {
    cin.tie(0);
    cout.tie(0);
    ios_base::sync_with_stdio(false);
	int q;
	cin >> q;

	for (int k=0; k<q; k++)
    {
        int n,m,a,b;
        cin >> n >> m >> a >> b;
        a--;
        b--;
        g.clear();
        ans.clear();
        g.resize(n);
        for (int i=0; i<m; i++)
        {
            int l,r;
            cin >> l >> r;
            l--;
            r--;
            g[l].push_back(r);
            g[r].push_back(l);
        }

        timer = 0;
        for (int i=0; i<n; i++) used[i]=false;
        dfs(0);
        bool ok = 0;
        bool ok1 = 0;
        for (auto i:ans)
        {
            if (i==a) ok=1;
            if (i==b) ok1=1;
        }

        if (!ok || !ok1)
        {
            cout << 0 << endl;
            continue;
        }

        for (int i=0; i<n; i++)
        {
            used[i]=0;
            a1[i]=0;
        }

        check(a,b,1);
        for (int i=0; i<n; i++) used[i]=false;
        check(b,a,2);
        int otv1 = 0;
        int otv2 = 0;
        for (int i=0; i<n; i++)
        {
            if (a1[i]==1) otv1++;
            if (a1[i]==2) otv2++;
        }

        cout << (otv1-1)*(otv2-1) << endl;
    }
}


#include <string>
#include <fstream>
#include <queue>
#include <iostream>
#include <algorithm>
#include <stack>
#include <vector>
#include <set>
#include <math.h>
#include <cmath>
#include <map>
#include <unordered_map>

using namespace std;

vector<int> used;
vector<int> used2;
vector<vector<int>> g;
int cnt = 0;
int cnt2 = 0;
int a, b;

void dfs(int v)
{
    used[v] = cnt;
    cnt2 += 1;
    for (int i = 0; i < g[v].size(); ++i)
    {
        if (used[g[v][i]] == -1 && g[v][i] != a && g[v][i] != b)
        {
            dfs(g[v][i]);
        }
    }
}

int main() {
    std::ios::sync_with_stdio(0);
    int t;
    cin >> t;
    vector<int> comp;
    vector<int> ar3;
    for (int q = 0; q < t; ++q)
    {
        int n, m;
        cin >> n >> m;
        cin >> a >> b;
        comp.resize(0);
        g.resize(n);
        cnt = 0;
        cnt2 = 0;
        for (int i = 0; i < n; ++i)
        {
            g[i].resize(0);
        }
        used = vector<int>(n, -1);
        a -= 1;
        b -= 1;
        for (int i = 0; i < m; ++i)
        {
            int v, u;
            cin >> v >> u;
            v--, u--;
            g[v].push_back(u);
            g[u].push_back(v);
        }
        for (int i = 0; i < n; ++i)
        {
            cnt2 = 0;
            if (used[i] == -1 && i != a && i != b)
            {
                used[i] = cnt;
                dfs(i);
                comp.push_back(cnt2);
                cnt += 1;
            }
        }
        int64_t ans1 = 0;
        ar3 = vector<int>(comp.size(), -1);
        int64_t ans2 = 0;
        for (int i = 0; i < g[a].size(); ++i)
        {
            if (g[a][i] == b)
                continue;
            else
            {
                if (ar3[used[g[a][i]]] == -1)
                {
                    ans1 += comp[used[g[a][i]]];
                    ar3[used[g[a][i]]] = 1;
                }
            }
        }
        for (int i = 0; i < g[b].size(); ++i)
        {
            if (g[b][i] == b)
                continue;
            else
            {
                if (ar3[used[g[b][i]]] == -1)
                {
                    ans2 += comp[used[g[b][i]]];
                    ar3[used[g[b][i]]] = 2;
                }
                else if (ar3[used[g[b][i]]] == 1)
                {
                    ans1 -= comp[used[g[b][i]]];
                    ar3[used[g[b][i]]] = 2;
                }
            }
        }
        cout << ans1 * ans2 << endl;
    }
}


#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

//ifstream in("input.txt");
//ofstream out("output.txt");

void dfs(vector<vector<int>>& g, vector<bool>& vis, int u, int& cnt)
{
	cnt++;
	vis[u] = true;
	for (int i = 0; i < g[u].size(); i++)
	{
		if (vis[g[u][i]] == false)
			dfs(g, vis, g[u][i], cnt);
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int q; cin >> q;
	for (int qq = 0; qq < q; qq++)
	{
		int n, m, a, b;
		cin >> n >> m >> a >> b;
		vector<vector<int>> g(n);
		int u = 0, v = 0;
		for (int i = 0; i < m; i++)
		{
			cin >> u >> v;
			g[u - 1].push_back(v - 1);
			g[v - 1].push_back(u - 1);
		}
		vector<bool> vis(n, false);
		vis[a-1] = true; vis[b-1] = true;
		int cnt1 = 0;
		dfs(g, vis, a - 1, cnt1);
		for (int i = 0; i < n; i++)
			vis[i] = false;
		vis[a - 1] = true;
		vis[b - 1] = true;
		int cnt2 = 0;
		dfs(g, vis, b - 1, cnt2);
		int dif = cnt1 + cnt2 - n;
		cnt1 -= dif;
		cnt2 -= dif;
		cout << (long long)(cnt1 - 1) * (cnt2 - 1) << '\n';
	}
}