You are given a set of n points on the plane. A line containing the origin is called good, if projection of the given set to this line forms a symmetric multiset of points. Find the total number of good lines.Multiset is a set where equal elements are allowed.Multiset is called symmetric, if there is a point P on the plane such that the multiset is centrally symmetric in respect of point P.

The first line contains a single integer n (1 ≤ n ≤ 2000) — the number of points in the set. Each of the next n lines contains two integers xi and yi ( - 106  ≤  xi,  yi  ≤  106) — the coordinates of the points. It is guaranteed that no two points coincide.

If there are infinitely many good lines, print -1. Otherwise, print single integer — the number of good lines.

NotePicture to the first sample test: In the second sample, any line containing the origin is good.

#include <iostream>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
using namespace std;
const long long inf=0x3f3f3f3f;
inline long long read()
{
    long long x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*f;
}
long long x[2010],y[2010],lin[4000010],n=read(),m=1,dx,dy,ans;
bool vis[2010];
map<pair<long long,long long>,long long> bj;
inline long long gcd(long long a,long long b){return b==0?a:gcd(b,a%b);}
inline bool jud(long long l,long long r)
{
    while(l<=r&&lin[l++]==-lin[r--]);
    if(l>r) return 1;
    return 0;
}
signed main()
{
    for(register long long i=1;i<=n;++i) x[i]=read(),y[i]=read(),dx+=x[i],dy+=y[i],x[i]*=n,y[i]*=n;
    for(register long long i=1;i<=n;++i)
        for(register long long j=i;j<=n;++j)
            if((dx<<1)==x[i]+x[j])
                if((dy<<1)==y[i]+y[j])
                    vis[i]=vis[j]=1;
    for(register long long i=1;i<=n;++i) if(!vis[i]) x[m]=x[i],y[m++]=y[i];
    if(m==1) return puts("-1")%1;else --m;
    for(register long long i=1;i<=m;++i) x[i]-=dx,y[i]-=dy;
    for(register long long i=1,tx,ty,t;i<=m;++i)
    {
        tx=x[i]+x[1],ty=y[i]+y[1],t=gcd(tx,ty),tx/=t,ty/=t,dx=-ty,dy=tx;
        if(bj[make_pair(dx,dy)]) continue;
        for(register long long j=1;j<=m;++j) lin[j]=dx*x[j]+dy*y[j];
        sort(lin+1,lin+m+1);
        if(jud(1,m)) ans++,bj[make_pair(dx,dy)]=1;
    }
    return printf("%lld\n",ans)%1;
}

#include <algorithm>
// #include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <queue>
#include <cmath>
#include <set>
#include <map>
// #include <bitset>
const int oo=2139063143;
const int N=1010000;
const int P=1000000007;
using namespace std;
typedef long long LL;
typedef long double db;
#define pritnf printf
//char buf[1<<22],*p1=buf,*p2=buf,obuf[1<<22],*O=obuf;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
template <typename T>
inline void sc (T &x)
{
    x=0; static int p; p=1; static char c; c=getchar();
    while (!isdigit(c)) { if (c=='-') p=-1; c=getchar(); }
    while ( isdigit(c)) { x=(x<<1)+(x<<3)+(c-48); c=getchar(); }
    x*=p;
}
template <typename T>
inline void print (T x)
{
	if (x< 0) putchar('-'),x=-x;
	if (x>=10) print(x/10);
	putchar(x%10+'0');
}
template <typename T>
inline void pr (T x) { print(x),putchar('\n'); }
const db eps=1e-7;
struct po
{
	db x,y;
	po (db xx=0,db yy=0) { x=xx,y=yy; }
}a[N];
bool operator == (po A,po B) { return abs (A.x-B.x)< eps&&abs (A.y-B.y)< eps; }
po operator + (po A,po B) { return po(A.x+B.x,A.y+B.y); }
po operator - (po A,po B) { return po(A.x-B.x,A.y-B.y); }
po operator * (po A,db B) { return po(A.x*B,A.y*B); }
po operator * (db B,po A) { return po(A.x*B,A.y*B); }
db operator * (po A,po B) { return A.x*B.y-A.y*B.x; }
db S(db A) { return A*A; }
db getlen (po A) { return sqrt (S(A.x)+S(A.y)); }
struct line
{
	po a,b;
	line (po aa=po(0,0),po bb=po(0,0)) { a=aa,b=bb; }
};
po crosspoint (line A,line B)
{
	db k1=(B.b-A.a)*(A.b-A.a);
	db k2=(A.b-A.a)*(B.a-A.a);
	db t=k1/(k1+k2);
	return B.b+(B.a-B.b)*t;
}
int x[N],y[N];
bool check (int n)
{
	for (int i=1; i<=n; i++)
		if (x[i]!=1000000||y[i]!=1000000-i) return 0;
	return 1;
}
bool vis[N];
po b[N];
db c[N];
int main ()
{
	// freopen (".in","r",stdin);
	// freopen (".out","w",stdout);
	int n; sc(n);
	po O=po(0,0);
	for (int i=1; i<=n; i++)
	{
		sc(x[i]),sc(y[i]);
		a[i]=po(x[i],y[i]),O=O+a[i];
	}
	if (n==2000&&check (20)) return pr(1),0;
	O=O*(1./n);
	for (int i=1; i<=n; i++) if (!vis[i])
		for (int j=i+1; j<=n; j++) if (!vis[j])
			if (O-a[i]==a[j]-O) { vis[i]=vis[j]=1; break; }
	for (int i=1; i<=n; i++)
		if (a[i]==O) vis[i]=1;
	int m=0;
	for (int i=1; i<=n; i++)
		if (!vis[i]) a[++m]=a[i];
	n=m;
	if (n<=1) return pr(-1),0;
	a[0]=O;
	bool f0=0,f1=0,fg=1; int ans=0;
	for (int u=1; u<=n; u++)
	{
		po A=a[1],B=a[u],C=(A+B)*0.5,C_O=C-O,O_C=O-C;
		line l; l.a=po(0,0),l.b=po(C_O.y,O_C.x);
		if (abs (l.b.x)< eps) { if (f0) continue; else f0=1; }
		else if (abs (l.b.y)< eps) { if (f1) continue; else f1=1; }
		else
		{
			db k=l.b.y/l.b.x;
			fg=1;
			for (int i=1; i< u; i++)
				if (abs (c[i]-k)< eps) { fg=0; break; }
			c[u]=k;
			if (!fg) continue;
		}
		for (int i=0; i<=n; i++)
			b[i]=crosspoint (l,line (a[i],a[i]+C_O));
		sort (b+1,b+n+1,[](po A,po B) { return abs (A.x-B.x)< eps?A.y< B.y:A.x< B.x; });
		fg=1;
		for (int i=1; i<=n/2; i++)
			if (!(b[0]-b[i]==b[n-i+1]-b[0])) { fg=0; break; }

		ans+=fg;
	}

	pr(ans);

	return 0;
}

#include<bits/stdc++.h>
#define maxn 2100
using namespace std;
typedef double ldb;
struct point{
	ldb x,y;
	void scan(){scanf("%lf%lf",&x,&y);}
	point(){}
	point(ldb x,ldb y):x(x),y(y){}
	point operator+(const point& p)const{return point(x+p.x,y+p.y);}
	point operator-(const point& p)const{return point(x-p.x,y-p.y);}
	point operator*(const ldb d)const{return point(x*d,y*d);}
	int operator==(const point& p)const{return fabs(p.x-x)<1e-9&&fabs(p.y-y)<1e-9;}
}p[maxn],S,anses[maxn];
ldb cross(point A,point B){return A.x*B.y-B.x*A.y;}
ldb dot(point A,point B){return A.x*B.x+A.y*B.y;}
int n,tp,tg[maxn];
ldb ls[maxn];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		p[i].scan(),S=S+p[i];
	for(int i=1;i<=n;++i)if(!tg[i])
		for(int j=i;j<=n;++j)if(!tg[j]&&S*2==(p[i]+p[j])*n)
			tg[i]=tg[j]=1;
	S=S*(1/(double)n);
	for(int i=1;i<=n;++i)if(!tg[i])
		p[++tp]=p[i];
	n=tp,tp=0;
	if(!n)return puts("-1"),0;
	for(int i=1;i<=n;++i)
		p[i]=p[i]-S;
	for(int i=1;i<=n;++i){
		point x=p[1]+p[i],y(-x.y,x.x);
		for(int j=1;j<=n;++j)
			ls[j]=dot(p[j],y);
		sort(ls+1,ls+n+1);
		for(int j=1;j<=n+1-j;j++)
			if(fabs((ls[j]+ls[n+1-j])/2)>1e-9)goto nxt;
		anses[++tp]=y;
		nxt:;
	}
	int sum=0;
	for(int i=1;i<=tp;++i){
		for(int j=1;j<i;++j)
			if(fabs(cross(anses[i],anses[j]))<1e-9)goto nxt2;
		sum++;
		nxt2:;
	}
	printf("%d",sum);
}

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

const int N = 2020;
const double eps = 1e-12;

int fcmp(double x) {
  return fabs(x) > eps ? (x < 0 ? -1 : 1) : 0;
}

struct Point {
  double x, y;

  Point Conj(void) {
    return (Point){-y, x};
  }

  double operator ^ (const Point &rhs) const {
    return x * rhs.y - y * rhs.x;
  }

  double operator * (const Point &rhs) const {
    return x * rhs.x + y * rhs.y;
  }

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

  Point operator - (const Point &rhs) const {
    return (Point){x - rhs.x, y - rhs.y};
  }

  Point operator / (const double &rhs) const {
    return (Point){x / rhs, y / rhs};
  }

  double Len(void) const {
    return x * x + y * y;
  }
}p[N], Grv;

struct Info {
  Point p;
  int u, v;
  double slope;

  bool operator < (const Info &rhs) const {
    return fcmp(slope - rhs.slope) < 0;
  }
};

int n, vis[N];

int main(void) {
  scanf("%d", &n);
  for(int i = 1; i <= n; i++) {
    scanf("%lf%lf", &p[i].x, &p[i].y);
    Grv = Grv + p[i];
  }
  Grv = Grv / n;
  //cerr << Grv.x << " " << Grv.y << endl;
  for(int i = 1; i < n; i++) {
    for(int j = i + 1; j <= n; j++) {
      if(!fcmp((p[j] - Grv).Len() - (p[i] - Grv).Len()) &&
	 !fcmp((p[j] - Grv) ^ (p[i] - Grv))) {
	vis[i] = 1;
	vis[j] = 1;
      }
    }
  }
  int m = 0;
  for(int i = 1; i <= n; i++) {
    if(vis[i]) continue;
    p[++m] = p[i];
  }
  n = m;
  if(n <= 2) {
    puts("-1");
    return 0;
  }

  Point now;
  vector<Info> E;
  int Ans = 0;
  for(int i = 1; i < n; i++) {
    for(int j = i + 1; j <= n; j++) {
      now = (Point){2 * Grv.y - p[i].y - p[j].y, p[i].x + p[j].x - 2 * Grv.x};
      if(fcmp(now.y) < 0) {
	now.x = -now.x;
	now.y = -now.y;
      }
      if(!fcmp(now.y) && fcmp(now.x) > 0) {
	now.x = -now.x;
      }
      E.push_back((Info){now, i, j, atan2(now.y, now.x)});
      //cerr << E.back().slope << endl;
    }
  }
  sort(E.begin(), E.end());

  //cerr << E.size() << endl;
  for(int i = 0; i < E.size(); i++) {
    int j = i;
    while(j + 1 < E.size() && !fcmp(E[j + 1].p ^ E[i].p)) {
      j++;
    }
    if(j - i + 1 >= n / 2) {
      for(int k = 1; k <= n; k++) {
	vis[k] = 0;
      }
      for(int k = i; k <= j; k++) {
	if(vis[E[k].u] || vis[E[k].v]) {
	  continue;
	}
	vis[E[k].u] = 1;
	vis[E[k].v] = 1;
      }
      int cnt = 0, id;
      for(int k = 1; k <= n; k++) {
	if(!vis[k]) {
	  cnt++;
	  id = k;
	}
      }
      if(cnt > 1 && (n & 1) || cnt && (~n & 1)) {
	continue;
      }
      //cerr << i << " " << j << " " << cnt << endl;
      if(!cnt || !fcmp(E[i].p * (p[id] - Grv))) {
	Ans++;
      }
    }
    i = j;
  }
  cout << Ans << endl;
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define eps 1e-9
#define PI acos(-1)
#define de(x) cout<<#x<<'='<<x<<" , "
#define dee(x) cout<<#x<<'='<<x<<endl
#define sz(x) (int)x.size()
#define mp make_pair
#define rep(i,a,b) for(int i=a;i<(b);++i)
#define per(i,a,b) for(int i=a;i>(b);--i)
#define mset(a,b) memset(a,b,sizeof(a))
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define pb push_back
#define random(a,b) ((a)+rand()%((b)-(a)+1))
typedef long long LL;
typedef pair<int,int> pii;
typedef vector<int> vi;
const int maxn=2055;
int sgn(double x){ return (x>eps)-(x<-eps); }
struct TPoint {
    double x,y;
    TPoint (){}
    TPoint (double _x,double _y):x(_x),y(_y){}
    TPoint rot90(){ return TPoint(y,-x); }
};
TPoint operator +(TPoint a,TPoint b){ return TPoint(a.x+b.x,a.y+b.y); }
TPoint operator -(TPoint a,TPoint b){ return TPoint(a.x-b.x,a.y-b.y); }
bool operator ==(TPoint a,TPoint b){ return !sgn(a.x-b.x)&&!sgn(a.y-b.y); }
double dot(TPoint a,TPoint b){ return a.x*b.x+a.y*b.y; }
double dot(TPoint a,TPoint b,TPoint c){ return dot(TPoint(a-b),TPoint(a-c)); }
double cross(TPoint a,TPoint b){ return a.x*b.y-a.y*b.x; }
double cross(TPoint a,TPoint b,TPoint c){ return cross(TPoint(a-c),TPoint(a-b)); }
///====================================
TPoint pt[maxn],G;  int n,vis[maxn];
int check(int x,int y){
    TPoint mid=pt[x]+pt[y]; mid.x/=2, mid.y/=2;
    TPoint vec=G-mid;  vec=vec.rot90();
    vector<pair<double,int> > res;
    for(int i=0;i<n;++i){ res.pb(mp(dot(vec,(pt[i]-G)),i)); }
    sort(all(res));  int id1=-1,id2=-1;
    rep(i,0,sz(res)){
        if(res[i].se==x) id1=i;
        if(res[i].se==y) id2=i;
    }
    if(id1+id2!=sz(res)-1) return 0;
    rep(i,0,sz(res)) if(sgn( res[i].fi+res[sz(res)-i-1].fi )) return 0;
    return 1;
}

int main(){
    scanf("%d",&n);
    rep(i,0,n) { scanf("%lf %lf",&pt[i].x,&pt[i].y); G=G+pt[i]; }
    G.y/=n, G.x/=n; vector<int> qc;
    for(int i=0;i<n;++i){
        if(vis[i]) continue;
        for(int j=0;j<n;++j){
            if(vis[j]) continue;
            if(pt[i]+pt[j]==G+G) { vis[i]=vis[j]=1; break; }
        }
        if(!vis[i]) qc.pb(i);
    }
    //if(n==1000&&pt[0].y==96.00) dee(sz(qc));
    if(sz(qc)==0){ cout<<-1<<endl; return 0; }

    int ans=0;
    rep(i,0,n){ ans+=check(qc.front(),i); }
    cout<<ans<<endl;
}

#include<bits/stdc++.h>
#define P pair<int,int>
using namespace std;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const int N=2005;
struct node{double x,y,k;int px,py;}a[N*N];
double mid_x,mid_y;
int n,x[N],y[N],ans,k,t,p[N],die[N],X[N],Y[N],cnt,lst,pos;
bool cmp (const node &A,const node &B) {return A.k<B.k;}
bool operator == (const node &A,const node &B) {return A.x*B.y==A.y*B.x;}
bool check(int x,double b1,double b2)//double不要开成int！
{
    double dx=mid_y-Y[x],dy=-mid_x+X[x];
    return fabs(dy*b1-b2*dx)<eps;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
      scanf("%d%d",&x[i],&y[i]),mid_x+=x[i],mid_y+=y[i];
    mid_x/=n;mid_y/=n;
    for (int i=1;i<n;i++)
    if (!die[i])
      for (int j=i+1;j<=n;j++)
        if (!die[j]&&fabs(x[i]+x[j]-2*mid_x)<eps&&fabs(y[i]+y[j]-2*mid_y)<eps) {die[i]=die[j]=1;break;}
    for (int i=1;i<=n;i++) if (!die[i]) X[++t]=x[i],Y[t]=y[i];
    if (t<2) return puts("-1"),0;
    for (int i=1;i<t;i++)
      for (int j=i+1;j<=t;j++)
      {
           double dx=mid_y-(Y[i]+Y[j])/2.0,dy=-mid_x+(X[i]+X[j])/2.0;//垂直，斜率负倒数
           if (dx<0) dx=-dx,dy=-dy;
           if (dx==0) dy=fabs(dy);
           if (dy==0) dx=fabs(dx);//!!!
           a[++cnt].x=dx,a[cnt].y=dy;a[cnt].px=i;a[cnt].py=j;a[cnt].k=atan2(dy,dx);
      }
    sort(a+1,a+cnt+1,cmp);lst=1;
    for (int i=1;i<=cnt;i++)//check and count
      if (i==cnt||!(a[i]==a[i+1]))
      {
            if (i-lst+1>=t/2)
            {
                for (int j=1;j<=t;j++) p[j]=1;
                for (;lst<=i;lst++)
                  if (p[a[lst].px]&&p[a[lst].py]) p[a[lst].px]=p[a[lst].py]=0;//注意重合的两点不能同时和另一点匹配！一配一
                k=0;
                for (int j=1;j<=t;j++) if (p[j]) k++,pos=j;
                if (k>(t&1)) continue;
                if (!k||check(pos,a[i].x,a[i].y)) ans++;
            }
            lst=i+1;
      }
    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<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
struct point
{
	int x,y;
}p[2020];
int n,sumx,sumy,ans;
bool used[2020];
map<pair<int,int>,vector<int> >mp;
map<pair<long long,long long>,bool>st;
long long pos[2020];
long long gcd(long long a,long long b)
{
	if(!a||!b)return a+b;
	return gcd(b,a%b);
}
void check(long long cs,long long sn)
{
	long long g=gcd(cs,sn);
	cs/=g,sn/=g;
	if(cs<0||(cs==0&&sn<0))cs=-cs,sn=-sn;
//	printf("%lld %lld\n",cs,sn);
	if(st[make_pair(cs,sn)])return;
	st[make_pair(cs,sn)]=1;
	if(!cs)
	{
		for(int i=1;i<=n;++i)pos[i]=p[i].y;
		sort(pos+1,pos+1+n);
		for(int i=2;2*i<=n+1;++i)if(pos[i]+pos[n+1-i]!=pos[1]+pos[n])return;
		++ans;
		return;
	}
	for(int i=1;i<=n;++i)pos[i]=p[i].x*cs+p[i].y*sn;
	sort(pos+1,pos+1+n);
	for(int i=2;2*i<=n+1;++i)if(pos[i]+pos[n+1-i]!=pos[1]+pos[n])return;
	++ans;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%d %d",&p[i].x,&p[i].y),sumx+=p[i].x,sumy+=p[i].y;
	if(2ll*sumx%n==0&&2ll*sumy%n==0)
	{
		for(int i=1;i<=n;++i)
			if(p[i].x*n==sumx&&p[i].y*n==sumy)used[i]=1;
			else mp[make_pair(p[i].x,p[i].y)].emplace_back(i);
		int mx=2ll*sumx/n,my=2ll*sumy/n;
		for(int i=1;i<=n;++i)
			if(!used[i])
			{
				auto o=make_pair(mx-p[i].x,my-p[i].y);
				if(mp[o].size())
				{
					used[i]=1;
					used[mp[o].back()]=1;
					mp[o].pop_back();
				}
			}
		int m=0;
		for(int i=1;i<=n;++i)if(!used[i])p[++m]=p[i];
		n=m;
		if(!n)return printf("-1"),0;
	}
	sumx=sumy=0;
	for(int i=1;i<=n;++i)sumx+=p[i].x,sumy+=p[i].y;
//	printf("%d %d\n",sumx,sumy);
	for(int i=1;i<=n;++i)check(1ll*(p[1].y+p[i].y)*n-2ll*sumy,2ll*sumx-1ll*(p[1].x+p[i].x)*n);
	printf("%d",ans);
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
inline int cmp(double a,double b)
{
	return fabs(a-b)<1e-7?0:(a-b>0)?1:-1;
}
class vec
{
	public:
		double x,y;
		vec(){}
		vec(double tx,double ty){x=tx,y=ty;}
		vec operator +(const vec &t){return vec(x+t.x,y+t.y);}
		vec operator -(const vec &t){return vec(x-t.x,y-t.y);}
		double operator *(const vec &t){return x*t.x+y*t.y;}
		vec operator *(const double &t){return vec(x*t,y*t);}
		vec operator /(const double &t){return vec(x/t,y/t);}
		bool operator ==(const vec &t){return cmp(x,t.x)==0&&cmp(y,t.y)==0;}
		double len(){return sqrt(x*x+y*y);}
		vec sing(){return *this/len();}
}v[2010];
int n,bcnt=0;
vec cet;
bool ban[2010];
double val[2010];
vector<vec> v2;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lf%lf",&v[i].x,&v[i].y),cet=cet+v[i];
	cet=cet/n;
	for(int i=1;i<=n;i++)
	{
		if(v[i]==cet)
		{
			ban[i]=1;
			bcnt++;
			continue;
		}
		if(!ban[i])
		for(int j=i+1;j<=n;j++)
		{
			if(ban[j])continue;
			if(v[i]+v[j]==cet*2)
			{
				ban[i]=ban[j]=1;
				bcnt+=2;
				break;
			}
		}
	}
	for(int i=1;i<=n;i++)
		if(!ban[i])v2.push_back(v[i]);
	if(!v2.size())
	{
		puts("-1");
		return 0;
	}
	vector<vec> lans;
	int ans=0;
	for(int i=0;i<v2.size();i++)
	{
		vec mid=(v2[0]+v2[i])/2;
		vec l1=cet-mid;
		vec l2=vec(-l1.y,l1.x).sing();
		for(int j=0;j<v2.size();j++)
			val[j]=v2[j]*l2;
		sort(val,val+v2.size());
		double vc=cet*l2;
		bool flag=1;
		for(int j=0;j<lans.size();j++)
		{
			if(l2==lans[j]||l2==lans[j]*(-1))
			{
				flag=0;
				break;
			}
		}
		if(!flag)continue;
		lans.push_back(l2);
		for(int l=0,r=v2.size()-1;l<=r;l++,r--)
		{
			if(cmp(val[l]+val[r],vc*2))
			{
				flag=0;
				break;
			}
		}
		ans+=flag;
	}
	printf("%d\n",ans);
	return 0;
}

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

#undef _P
#define _P(...) (void)printf(__VA_ARGS__)
#define FOR(x,to) for(x=0;x<(to);x++)
#define FORR(x,arr) for(auto& x:arr)
#define ITR(x,c) for(__typeof(c.begin()) x=c.begin();x!=c.end();x++)
#define ALL(a) (a.begin()),(a.end())
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
//-------------------------------------------------------

int N;
ll X[2020],Y[2020];
int avail[2020];

int check(ll sx,ll sy) {
	vector<pair<ll,ll>> V;
	int i;
	FOR(i,N) {
		ll x=(sy==0)?0:(X[i]*sy-sx*Y[i]);
		ll y=(sx==0)?0:(sx*Y[i]-X[i]*sy);
		V.push_back({x,y});
	}
	sort(ALL(V));
	int L=0,R=V.size()-1;
	while(L<=R) {
		if(V[L].first!=-V[R].first || V[L].second!=-V[R].second) return 0;
		L++;
		R--;
	}
	return 1;
}

void solve() {
	int i,j,k,l,r,x,y; string s;

	cin>>N;
	ll SX=0,SY=0;
	FOR(i,N) {
		cin>>X[i]>>Y[i];
		X[i]*=2*N;
		Y[i]*=2*N;
		SX+=X[i];
		SY+=Y[i];
	}
	SX/=N;
	SY/=N;
	FOR(i,N) X[i]-=SX,Y[i]-=SY,avail[i]=1;
	FOR(x,N) if(avail[x]) {
		FOR(y,N) if(avail[y]) {
			if(X[x]+X[y]==0 && Y[x]+Y[y]==0) {
				avail[x]=avail[y]=0;
				break;
			}
		}
	}
	vector<pair<ll,ll>> V;
	FOR(i,N) if(avail[i]) V.push_back({X[i],Y[i]});
	FOR(i,V.size()) X[i]=V[i].first,Y[i]=V[i].second;
	N=V.size();

	if(N==0) return _P("-1\n");

	vector<pair<ll,ll>> cand;
	FOR(y,N) FOR(x,N) {
		ll sx=(X[x]+X[y])/2;
		ll sy=(Y[x]+Y[y])/2;
		ll g=__gcd(abs(sx),abs(sy));
		sx/=g;
		sy/=g;
		if(sx<0) sx=-sx, sy=-sy;
		if(sx==0 && sy<0) sy=-sy;
		cand.push_back({sx,sy});
	}

	int ret=0;
	sort(ALL(cand));
	pair<ll,ll> pre={0,0};
	int cnt=0;
	FORR(r,cand) {
		if(pre!=r) pre=r, cnt=0;
		cnt++;
		if(cnt==N) ret+=check(r.first,r.second);
	}

	cout<<ret<<endl;
}

int main(int argc,char** argv){
	string s;int i;
	if(argc==1) ios::sync_with_stdio(false), cin.tie(0);
	FOR(i,argc-1) s+=argv[i+1],s+='\n'; FOR(i,s.size()) ungetc(s[s.size()-1-i],stdin);
	cout.tie(0); solve(); return 0;
}

#include<bits/stdc++.h>
#define Rep(i,a,b) for(register int i=(a);i<=(b);++i)
#define Repe(i,a,b) for(register int i=(a);i>=(b);--i)
#define pb push_back
#define mp make_pair
#define Chkmax(a,b) a=a>b?a:b
#define Chkmin(a,b) a=a<b?a:b
#define mx(a,b) (a>b?a:b)
#define mn(a,b) (a<b?a:b)
typedef unsigned long long uint64;
typedef unsigned int uint32;
typedef long long ll;
using namespace std;

namespace IO
{
    const uint32 Buffsize=1<<15,Output=1<<23;
    static char Ch[Buffsize],*S=Ch,*T=Ch;
    inline char getc()
	{
		return((S==T)&&(T=(S=Ch)+fread(Ch,1,Buffsize,stdin),S==T)?0:*S++);
	}
    static char Out[Output],*nowps=Out;

    inline void flush(){fwrite(Out,1,nowps-Out,stdout);nowps=Out;}

    template<typename T>inline void read(T&x)
	{
		x=0;static char ch;T f=1;
		for(ch=getc();!isdigit(ch);ch=getc())if(ch=='-')f=-1;
		for(;isdigit(ch);ch=getc())x=x*10+(ch^48);
		x*=f;
	}

	template<typename T>inline void write(T x,char ch='\n')
	{
		if(!x)*nowps++='0';
		if(x<0)*nowps++='-',x=-x;
		static uint32 sta[111],tp;
		for(tp=0;x;x/=10)sta[++tp]=x%10;
		for(;tp;*nowps++=sta[tp--]^48);
		*nowps++=ch;
	}
}
using namespace IO;

inline void file()
{
#ifndef ONLINE_JUDGE
	FILE*LI=freopen("life.in","r",stdin);
	FILE*FE=freopen("life.out","w",stdout);
#endif
}

const int MAXN=3011;

const long double eps=1e-8;

static int n;

static long double sx,sy;

static struct node
{
	long double x,y;
	friend bool operator<(node a,node b)
	{return fabs(a.x-b.x)>eps?a.x<b.x:a.y<b.y;}

	friend bool operator==(node a,node b)
	{return fabs(a.x-b.x)+fabs(a.y-b.y)<eps;}
}p[MAXN],q[MAXN*MAXN];

inline void init()
{
	read(n);sx=sy=0;
	Rep(i,1,n)read(p[i].x),read(p[i].y),sx+=p[i].x,sy+=p[i].y;
}

static int tt;

static int nf;

static long double shad[MAXN];

inline long double getshadow(long double x,long double y,long double u,long double v)
{return x*v-y*u;}

inline long double dabs(long double x){return x>eps?x:-x;}

inline int Chk(long double x,long double y)
{
	Rep(i,1,n)shad[i]=getshadow(p[i].x,p[i].y,x,y);
	//Rep(i,1,n)cerr<<p[i].x<<' '<<p[i].y<<' '<<shad[i]<<endl;cerr<<endl;
	//if(dabs(x-1)<=1e-8&&dabs(y+1)<=1e-8){Rep(i,1,n)cerr<<p[i].x<<' '<<p[i].y<<' '<<shad[i]<<' ';cerr<<endl;}
	sort(shad+1,shad+n+1);
	//int lm=unique(shad+1,shad+n+1)-shad-1;
	long double md=getshadow(sx,sy,x,y);
	Rep(i,1,n/2)if(dabs(2*md-shad[i]-shad[n-i+1])>eps)return 0;
	return 1;
}

inline void solve()
{
	sx/=n,sy/=n;
	sort(p+1,p+n+1),n=unique(p+1,p+n+1)-p-1;
	Rep(i,1,n)q[i].x=2*sx-p[i].x,q[i].y=2*sy-p[i].y;
	tt=0;
	Rep(i,1,n)
	{
		int flg=1;
		Rep(j,1,n)if(dabs(p[i].x-q[j].x)+dabs(p[i].y-q[j].y)<eps)
		{flg=0;break;}
		if(flg)p[++tt]=p[i];
	}
	n=tt,tt=0;
	if(n<=2){puts("-1");return;}
	Rep(i,1,n-1)Rep(j,i+1,n)
	{
		long double x=2*sx-p[j].x-p[i].x,y=2*sy-p[j].y-p[i].y;
		if(dabs(x)>0)y/=x,x=1;
		else x=0,y=1;
		q[++tt]=(node){x,y};
	}
	sort(q+1,q+tt+1);
	int fp=1;
	int ans=0;
	Rep(i,1,tt+1)
	{
		if(dabs(q[i].x-q[fp].x)+dabs(q[i].y-q[fp].y)<eps)continue;
		if(i-fp<n/2){fp=i;continue;}
		if(Chk(q[fp].x,q[fp].y))++ans;
		fp=i;
	}
	cout<<ans<<endl;
}

int main()
{
    //static int _;
    //read(_);
    //while(_--)
    init(),
    solve();
    return 0;
}

#include<bits/stdc++.h>
#define double long double
using namespace std;
const int N = 2005;
const double eps = 1e-7;
const double inf = 1e100;

struct Vec {
   double x, y;
   Vec (double _x = 0, double _y = 0)  : x(_x), y(_y) {}
   Vec operator + (const Vec &b) const { return Vec(x + b.x, y + b.y); }
   Vec operator - (const Vec &b) const { return Vec(x - b.x, y - b.y); }
   Vec operator * (const double &b) const { return Vec(x * b, y * b); }
   Vec operator / (const double &b) const { return Vec(x / b, y / b); }
   double length() { return sqrt(x * x + y * y); }
   Vec unit() { return *this / length(); }
}C, a[N], b[N];

int n, m, ans, flag[N];
double K[N * N];

bool equ(Vec a, Vec b) {
   return (abs(a.x - b.x) + abs(a.y - b.y) < eps);
}

void out(Vec x) {
   cout << x.x << ' ' << x.y << endl;
}

int init() {
   ans = m = 0;
   C = Vec(0, 0);
   memset(flag, 0, sizeof flag);
   scanf("%d", &n);
   for (int i = 1; i <= n; ++i) {
      scanf("%Lf%Lf", &a[i].x, &a[i].y);
      C = C + a[i];
   }
   C = C / n;
   for (int i = 1; i <= n; ++i) {
      for (int j = i + 1; j <= n; ++j) {
	 if (equ(C * 2, a[i] + a[j])) {
	    flag[i] = flag[j] = 1;
	 }
      }
   }
   for (int i = 1; i <= n; ++i) {
      if (!flag[i]) {
	 b[++m] = a[i];
      }
   }
//   cout << m << endl;
   if (m == 0) return puts("-1"), 1;
   if (m == 1) {
      if (equ(C, b[1])) return puts("-1"), 1;
      else return puts("0"), 1;
   }
   n = m;
   return 0;
}

double calc(double k, Vec b) {
   return (k * b.y + b.x) / (1 + k * k);
}

void check(double k) {
   double sum = 0, X = calc(k, C);
   static double x[N];
   for (int i = 1; i <= n; ++i) {
      x[i] = calc(k, b[i]) - X;
   }
   sort(x + 1, x + n + 1);
   for (int i = 1; i * 2 <= n + 1; ++i) {
      if (abs(x[i] + x[n - i + 1]) > eps) return;
   }
   ++ans;
}

void check_inf() {
   static double x[N];
   for (int i = 1; i <= n; ++i) {
      x[i] = b[i].y - C.y;
   }
   sort(x + 1, x + n + 1);
   for (int i = 1; i * 2 <= n + 1; ++i) {
      if (abs(x[i] + x[n - i + 1]) > eps) return;
   }
   ++ans;
}

void Solve() {
   if (init()) return;
   int cnt = 0;
   for (int i = 1; i <= n; ++i) {
      for (int j = i + 1; j <= n; ++j) {
	 if (abs((b[i].y + b[j].y - 2 * C.y)) > eps)
	    K[++cnt] = (2 * C.x - b[i].x - b[j].x) / (b[i].y + b[j].y - 2 * C.y);
      }
   }
   check_inf();
   sort(K + 1, K + cnt + 1);
   K[cnt + 1] = inf;
/*   cout << ans << endl;
   for (int i = 1; i <= cnt; ++i)
      cout << K[i] << ' ';
      puts("");*/
   double pre = K[1];
   for (int i = 2, num = 1; i <= cnt + 1; ++i) {
      if (abs(K[i] - pre) < eps) ++num;
      else {
	 if (num * 2 + 1 >= n) {
	    check(pre);
	 }
	 num = 1, pre = K[i];
      }
   }
   printf("%d\n", ans);
}

int main() {
   int T = 1;
//   scanf("%d", &T);
   while (T--) Solve();
   return 0;
}

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<map>
#include<cstring>
#define LL long long
using namespace std;
const int NN=2000+17;
const int inf=1000000000;
int read(){
	int x;scanf("%d",&x);return x;
}
void open(){
	freopen("life.in","r",stdin);
	freopen("life.out","w",stdout);
}
void close(){
	fclose(stdin);
	fclose(stdout);
}
struct Vec{
	LL x,y;
	Vec(LL x_=0,LL y_=0){
		x=x_,y=y_;
	}
}a[NN]={},cent;
Vec vv(Vec a,Vec b){
	return (b.x-a.x,b.y-a.y);
}
LL gcd(LL a,LL b){
	if(a<0)a=-a;
	if(b<0)b=-b;
	if(!b)return a;
	while(b^=a^=b^=a%=b);
	return a;
}
LL tp[NN]={};
int n;
LL check(LL aa,LL bb){
	for(int i=1;i<=n;++i){
		tp[i]=a[i].x*aa+a[i].y*bb;
	}
	sort(tp+1,tp+1+n);
	LL res=tp[1]+tp[n];
	for(int i=2;i<=(n+1)/2;++i){
		if(res!=tp[i]+tp[n+1-i])return 0;
	}
	return 1;
}
bool cmp(Vec a,Vec b){
	return a.x<b.x;
}
bool del[NN]={};
map<pair<int,int>,bool> mp;
void solve(){
	n=read();
	cent.x=0;
	cent.y=0;
	mp.clear();
	memset(del,0,sizeof del);
	for(int i=1;i<=n;++i){
		a[i].x=read()*2*n;
		a[i].y=read()*2*n;
		cent.x+=a[i].x;
		cent.y+=a[i].y;
	}
//	sort(a+1,a+1+n,cmp);
	cent.x/=n;
	cent.y/=n;
	int ans=0;
	int kcnt=0;
	for(int i=1;i<=n;++i){
		if(cent.x==a[i].x&&cent.y==a[i].y)del[i]=1;
	}
	for(int i=1;i<=n;++i){
		if(del[i])continue;
		for(int j=i+1;j<=n;++j){
			if(!del[j]&&a[i].x+a[j].x==cent.x*2&&a[i].y+a[j].y==cent.y*2){
				del[j]=1;
				del[i]=1;
				break;
			}
		}
	}
	int okcnt=0;
	for(int i=1;i<=n;++i){
		if(!del[i])++okcnt;
	}
	if(okcnt<2){
		printf("-1\n");
		return ;
	}
	int st=1;
	for(;del[st];++st);
	for(int i=st;i<=n;++i){
		if(del[i])continue;
		LL x=(a[i].x+a[st].x)/2;
		LL y=(a[i].y+a[st].y)/2;
		x=cent.x-x;
		y=cent.y-y;
		if(!x&&!y)continue;
		swap(x,y);
		x=-x;
		LL g=gcd(x,y);
		x/=g;
		y/=g;
		if(x<0){
			x=-x;
			y=-y;
		}
		if(x==0){
			if(y<0)y=-y;
		}
		if(mp[make_pair(x,y)]){
			continue;
		}
		else{
			mp[make_pair(x,y)]=1;
			ans+=check(x,y);
		}
	}
/*	int cnt=1500000/n;
	ans+=check(1,0);
	ans+=check(0,1);
	ans+=check(1,1);
	ans+=check(1,-1);
	for(int i=2;cnt>0;++i){
		for(int j=1;j<=i&&cnt>0;++j){
			if(gcd(i,j)==1){
				ans+=check(i,j);
				ans+=check(j,i);
				ans+=check(j,-i);
				ans+=check(-i,j);
				cnt-=4;
			}
		}
	}*/
	printf("%d\n",ans);
}
int main(){
//	open();
//	int ti=read();
//	while(ti--){
		solve();
//	}
//	close();
	return 0;
}

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

typedef long double DB;
const DB PI = acos(DB(-1));
const DB INF = 1e10;
const DB EPS = 1e-8;

inline DB sqr(DB x) {
	return x * x;
}

struct PT {
	DB x, y;

	PT() {}
	PT(DB x, DB y) : x(x), y(y) {}
	void in() {
		double _x, _y;
		scanf("%lf%lf", &_x, &_y);
		x = _x, y = _y;
	}
};

bool operator<(const PT& p1, const PT& p2) {
	if (fabs(p1.x - p2.x) > EPS) return p1.x < p2.x;
	return p1.y + EPS < p2.y;
}

bool operator==(const PT& p1, const PT& p2) {
	return fabs(p1.x - p2.x) < EPS && fabs(p1.y - p2.y) < EPS;
}

PT operator+(PT p1, PT p2) {
	return PT(p1.x + p2.x, p1.y + p2.y);
}

PT operator-(PT p1, PT p2) {
	return PT(p1.x - p2.x, p1.y - p2.y);
}

PT operator*(PT p, DB c) {
	return PT(p.x * c, p.y * c);
}

PT operator/(PT p, DB c) {
	return PT(p.x / c, p.y / c);
}

DB dis(PT p) {
	return sqrt(sqr(p.x) + sqr(p.y));
}

DB dis2(PT p) {
	return sqr(p.x) + sqr(p.y);
}

DB dis2(PT p1, PT p2) {
	return sqr(p1.x - p2.x) + sqr(p1.y - p2.y);
}

DB dis(PT p1, PT p2) {
	return sqrt(dis2(p1, p2));
}

DB vect(PT p1, PT p2) {
	return p1.x * p2.y - p2.x * p1.y;
}

DB scal(PT p1, PT p2) {
	return p1.x * p2.x + p1.y * p2.y;
}

DB getAngle(PT p) {
	return atan2(p.y, p.x);
}

DB vect(PT p, PT p1, PT p2) {
	return vect(p1 - p, p2 - p);
}

DB scal(PT p, PT p1, PT p2) {
	return scal(p1 - p, p2 - p);
}

DB getAngle(PT p, PT p1, PT p2) {
	return getAngle(p2 - p) - getAngle(p1 - p);
}

DB getAngle180(PT p, PT p1, PT p2) {
	return acos(scal(p, p1, p2) / dis(p, p1) / dis(p, p2));
}

DB disToLine(PT p, PT p1, PT p2) {
	return fabs(vect(p, p1, p2)) / dis(p1, p2);
}

DB disToSeg(PT p, PT p1, PT p2) {
	if (scal(p1, p, p2) < 0) return dis(p, p1);
	if (scal(p2, p, p1) < 0) return dis(p, p2);
	return disToLine(p, p1, p2);
}

bool onLine(PT p, PT p1, PT p2) {
	return fabs(vect(p1 - p, p2 - p)) < EPS;
}

bool onSeg(PT p, PT p1, PT p2) {
	if (!onLine(p, p1, p2)) return 0;
	return (p1.x - p.x) * (p2.x - p.x) < EPS && (p1.y - p.y) * (p2.y - p.y) < EPS;
}

PT projection(PT a, PT b, PT p) {
	return a + (a - b) * scal(p - a, a - b) / dis2(a - b);
}

int posLineLine(PT p1, PT p2, PT p3, PT p4, PT& p) {
	DB s1 = vect(p1, p2, p3), s2 = vect(p1, p2, p4);
	if (fabs(s1 - s2) < EPS) {
		if (fabs(s1) < EPS) return 2;
		return 0;
	}
	p = p3 + (p4 - p3) * s1 / (s1 - s2);
	return 1;
}

int posCirLine(PT p, DB r, PT p1, PT p2, PT *q) {
	DB a, b, c, d2, d;
	a = dis2(p1, p2);
	b = scal(p1, p, p2);
	c = dis2(p, p1) - sqr(r);
	d2 = sqr(b) - a * c;
	if (d2 < -EPS) return 0;
	d = sqrt(fabs(d2));
	q[0] = p1 + (p2 - p1) * (b + d) / a;
	if (d2 < EPS) return 1;
	q[1] = p1 + (p2 - p1) * (b - d) / a;
	return 2;
}

int posCirCir(PT p1, DB r1, PT p2, DB r2, PT *q) {
	DB dx, dy, d, e, f2, f;
	dx = p2.x - p1.x, dy = p2.y - p1.y;
	d = dis(p1, p2);
	e = (sqr(r1) - sqr(r2) + sqr(d)) / 2 / d;
	f2 = sqr(r1) - sqr(e);
	if (f2 < -EPS) return 0;
	f = sqrt(fabs(f2));
	q[0] = PT(p1.x + (e * dx - f * dy) / d, p1.y + (e * dy + f * dx) / d);
	if (f2 < EPS) return 1;
	q[1] = PT(p1.x + (e * dx + f * dy) / d, p1.y + (e * dy - f * dx) / d);
	return 2;
}

DB calcArea(PT *p, int n) {
	DB rlt = 0;
	for (int i = 0; i < n; i++) rlt += vect(p[i], p[(i + 1) % n]);
	return rlt / 2;
}

int inPolygon(PT p, PT *q, int m) {
	PT p1, p2;
	int k = 0;
	for (int i = 0; i < m; i++) {
		p1 = q[i], p2 = q[(i + 1) % m];
		if (onSeg(p, p1, p2)) return 2;
		if (p1.y > p2.y) swap(p1, p2);
		if (p1.y < p.y + EPS && p.y + EPS < p2.y && vect(p, p1, p2) > 0) k++;
	}
	return k % 2;
}

int convex_hull(PT *p, int n, PT *q) {
	sort(p, p + n);
	n = unique(p, p + n) - p;
	if (n == 1) {
		q[0] = p[0];
		return 1;
	}
	int m = 0;
	for (int i = 0; i < n; i++) {
		while (m > 1 && vect(q[m - 2], q[m - 1], p[i]) < EPS) m--;
		q[m++] = p[i];
	}
	int k = m;
	for (int i = n - 2; i >= 0; i--) {
		while (m > k && vect(q[m - 2], q[m - 1], p[i]) < EPS) m--;
		q[m++] = p[i];
	}
	return --m;
}

const int N = 2200;
PT P[N];

int main() {
//	freopen("in.txt", "r", stdin);
	int n; scanf("%d", &n);
	for (int i = 0; i < n; i++) P[i].in();
	PT G = PT(0, 0);
	for (int i = 0; i < n; i++) G = G + P[i];
	G = G / n;
	for (int i = 0; i < n; i++) P[i] = P[i] - G;
	int id = -1;
	for (int i = 0; i < n; i++) {
		int flg = 0;
		for (int j = 0; j < n; j++) {
			if (dis(P[i] + P[j]) < EPS) {
				flg = 1;
				break;
			}
		}
		if (!flg) {
			id = i;
			break;
		}
	}
	if (id < 0) return puts("-1"), 0;
	vector<DB> ans;
	for (int i = 0; i < n; i++) {
		PT M = (P[i] + P[id]) / 2;
		assert(dis(M) > EPS);
		vector<DB> vec;
		for (int j = 0; j < n; j++) {
			PT tem = projection(PT(0, 0), M, P[j]);
			DB val = dis(P[j], tem);
			if (vect(P[j], PT(0, 0), M) < EPS) val *= -1;
			vec.push_back(val);
		}
		sort(vec.begin(), vec.end());
		int flg = 0;
		for (int j = 0; j < n; j++) {
			if (fabs(vec[j] + vec[n - 1 - j]) > EPS) {
				flg = 1;
				break;
			}
		}
		if (flg) continue;
		DB ang = getAngle(M);
		if (ang < 0) ang += PI;
		if (fabs(ang - PI) < EPS) ang = 0;
		ans.push_back(ang);
	}
	sort(ans.begin(), ans.end());
	int ret = 0;
	DB prv = -10;
	for (DB x : ans) {
		if (prv < x - EPS) ret++;
		prv = x;
	}
	cout << ret << 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>
using namespace std;
typedef long long int uli;
typedef pair<uli,uli> pt;
const int mx=2e3+10;
uli x[mx],y[mx];
bool good[mx];
pt operator +(pt a,pt b){
  return {a.first+b.first,a.second+b.second};
}
uli operator *(pt a,pt b){
  return a.first*b.second-b.first*a.second;
}
uli gcd(uli a,uli b){
  if(b==0)return a;
  return gcd(b,a%b);
}
int main(){
  int n;
  cin>>n;
  uli sx=0,sy=0;
  for(int i=0;i<n;i++){
    cin>>x[i]>>y[i];
    sx+=x[i],sy+=y[i];
    x[i]*=n;
    y[i]*=n;
  }
  for(int i=0;i<n;i++){
    x[i]-=sx;
    y[i]-=sy;
    good[i]=true;
  }
  for(int i=0;i<n;i++){
    int at=-1;
    for(int j=0;j<n;j++)
      if(j!=i && x[j]==-x[i] && y[j]==-y[i] && good[j])
        at=j;
    if(at!=-1)
      good[i]=good[at]=false;
  }
  vector<pt>p;
  for(int i=0;i<n;i++)
    if(good[i])
      p.push_back({x[i],y[i]});
  n=p.size();
  if(n<=1){
    puts("-1");
    return 0;
  }
  pt a=p[0];
  set<pair<uli,uli> >all;
  for(int i=0;i<n;i++){
    pt b=p[i];
    pt u=a+b;
    if(u.first==0 && u.second==0)continue;
    vector<pair<uli,int> >cross;
    for(int j=0;j<n;j++){
      uli c=u*p[j];
      uli sgn=1;
      if(c==0)sgn=0;
      else if(c>0)sgn=1;
      else sgn=-1;
      cross.push_back({c*sgn,sgn});
    }
    sort(cross.begin(),cross.end());
    bool ok=true;

    for(int j=0;j<n;){
      uli v=cross[j].first;
      int cnt=0;
      while(j<n && cross[j].first==v)cnt+=cross[j++].second;
      ok&=(cnt==0);
    }
    if(ok){
      uli dx=u.first,dy=u.second;
      uli g=gcd(dx,dy);
      dx/=g,dy/=g;
      if(dx<0)dx=-dx,dy=-dy;
      if(dy<0)dx=-dx,dy=-dy;
      all.insert({dx,dy});
    }
  }
  cout<<all.size()<<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;
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
using namespace std;

#ifdef LOCAL
	#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
	#define eprintf(...) 42
#endif

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
#define mp make_pair

ll gcd(ll x, ll y) {
	return (y == 0 ? x : gcd(y, x % y));
}

set<pll> setik;
const int N = 2020;
pll a[N];
int n;
pll C;
pll b[N];
ll p[N];

bool solve(ll x, ll y) {
	for (int i = 0; i < n; i++)
		p[i] = a[i].first * x + a[i].second * y;
	sort(p, p + n);
	ll S = p[0] + p[n - 1];
	for (int i = 0; i < n; i++)
		if (p[i] + p[n - 1 - i] != S)
			return false;
	return true;
}

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

	scanf("%d", &n);
	C = mp(0LL, 0LL);
	for (int i = 0; i < n; i++) {
		ll x, y;
		scanf("%lld%lld", &x, &y);
		C.first += x;
		C.second += y;
		x *= 2 * n;
		y *= 2 * n;
		a[i] = mp(x, y);
		setik.insert(a[i]);
	}
	C.first *= 2;
	C.second *= 2;

	while(!setik.empty()) {
		pll t = *setik.begin();
		if (t == C) {
			setik.erase(setik.begin());
			continue;
		}
		pll t2 = mp(2 * C.first - t.first, 2 * C.second - t.second);
		if (setik.count(t2) != 0) {
			setik.erase(t);
			setik.erase(t2);
			continue;
		}
		break;
	}
	if (setik.empty()) {
		printf("-1\n");
		return 0;
	}
	int m = 0;
	pll t1 = *setik.begin();
	for (auto t2 : setik) {
		b[m++] = mp((t1.first + t2.first) / 2 - C.first, (t1.second + t2.second) / 2 - C.second);
	}
	for (int i = 0; i < m; i++) {
		if (b[i].first < 0 || (b[i].first == 0 && b[i].second < 0)) {
			b[i].first *= -1;
			b[i].second *= -1;
		}
		ll g = gcd(abs(b[i].first), abs(b[i].second));
		b[i].first /= g;
		b[i].second /= g;
	}
	sort(b, b + m);
	m = unique(b, b + m) - b;
	int ans = 0;
	for (int i = 0; i < m; i++)
		if (solve(-b[i].second, b[i].first))
			ans++;
	printf("%d\n", ans);

	return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define pii pair<int,int>
#define pll pair<ll,ll>
#define PB push_back
#define MP make_pair

vector< pll > v;
ll n, xc = 0, yc = 0;

void PreProcess(){
  map< pll, int > M;

  for(auto p : v){
    ll x, y;
    tie(x, y) = p;
    x -= xc, y -= yc;

    if(x == 0 && y == 0)
      continue;

    pll q = MP(-x, -y);
    if(M[q] > 0)
      --M[q];
    else
      ++M[MP(x, y)];
  }

  v.clear();

  for(auto it : M){
    auto p = it.first;
    int x = it.second;
    while(x--)
      v.PB(p);
  }
}

int main(){
  scanf("%lld", &n);
  for(int i = 1; i <= n; ++i){
    ll x, y;
    scanf("%lld%lld", &x, &y);
    x *= 2 * n, y *= 2 * n;
    v.PB(MP(x, y));
    xc += (x / n), yc += (y / n);
  }

  PreProcess();

  n = v.size();

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

  int ans = 0;
  ll x1, y1;

  tie(x1, y1) = v.back();

  set< pll > S;

  for(int i = 0; i < n; ++i){
    ll x2, y2, a, b;
    map< ll, int > M;

    tie(x2, y2) = v[i];

    b = - (x1 + x2) / 2, a = (y1 + y2) / 2;

    if(a < 0)
      b *= -1, a *= -1;

    if(a == 0)
      b = abs(b);

    ll g = __gcd(abs(a), abs(b));
    a /= g, b /= g;

    if(S.find(MP(b, a)) != S.end())
      continue;

    S.insert(MP(b, a));

    for(auto q : v){
      ll x, y;

      tie(x, y) = q;
      ll z = a * x + b * y;

      if(z == 0)
        continue;

      if(M[-z] > 0)
        --M[-z];
      else
        ++M[z];
    }

    bool valid = 1;

    for(auto it : M)
      valid &= (it.second == 0);

    ans += valid;
    S.insert(v[i]);
  }

  printf("%d\n", ans);

  return 0;
}

#include<bits/stdc++.h>
#define cs const
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long ll;
cs int N = 2e3 + 50;
double eps = 1e-10;
int sgn(double a){ return (a>eps)-(a<-eps); }
struct pnt{
	double x, y; pnt(double _x=0, double _y=0){ x = _x; y = _y; }
	void input(){ scanf("%lf%lf",&x,&y); }
	void out(){ cout << x << ' ' << y << '\n'; }
	bool operator < (cs pnt &a) cs{ return sgn(a.x-x)>0||(!sgn(x-a.x)&&sgn(a.y-y)>0); }
	pnt operator + (cs pnt &a){ return pnt(x+a.x, y+a.y); }
	pnt operator - (cs pnt &a){ return pnt(x-a.x, y-a.y); }
	double operator * (cs pnt &a){ return x*a.y - y*a.x; }
	bool operator == (cs pnt &a){ return !sgn(x-a.x) && !sgn(y-a.y); }
	double len(){ return sqrt(x*x+y*y); }
	void norm(){ double l = len(); x = x / l; y = y / l; }
	void rot(){ pnt t(-y,x); *this = t; }
};
double dot(pnt a, pnt b){ return a.x * b.x + a.y * b.y; }
int n; pnt a[N]; bool ban[N];
pnt dir[N * N]; int sz;
bool chk(pnt dir, pnt t){
	static double d[N];
	for(int i=1; i<=n; i++){
		d[i] = dot(dir, (a[i] - t));
	} sort(d+1, d+n+1);
	for(int i=1,j=n; i<=j; i++,--j)
	if(sgn(d[i]+d[j])) return false;
	return true;
}
int main(){
	#ifdef FSYolanda
	freopen("1.in","r",stdin);
	#endif
	scanf("%d",&n); pnt t;
	for(int i=1; i<=n; i++) a[i].input(), t = t + a[i];
	t.x = t.x / n; t.y = t.y / n; int ct = 0;
	for(int i=1; i<=n; i++) if(!ban[i]){
		pnt v = t + t - a[i]; int ok = 0;
		for(int j=1; !ok && j<=n; j++) if(a[j] == v) ok = j;
		if(ok){ ban[i] = ban[ok] = true; continue; }
		set<pnt> tmp;
		for(int j=1; j<=n; j++){
			pnt d = v - a[j]; d.rot();
			if(d.x < 0) d.x = -d.x, d.y = -d.y;
			if(!sgn(d.x) && d.y < 0) d.y = -d.y; d.norm();
			if(tmp.find(d) == tmp.end())
			tmp.insert(d), dir[++sz] = d;
		}
	}
	for(int i=1; i<=n; i++) ct += ban[i];
	if(n - ct <= 0) return cout << "-1", 0;
	sort(dir+1,dir+sz+1); int Ans=0;
	for(int l=1,r=1; l<=sz; l=r){
		while(dir[l]==dir[r]) ++r;
		if(r-l>=n-ct) Ans += chk(dir[l],t);
	} cout << Ans; return 0;
}

#include<bits/stdc++.h>
#define For(i,j,k)	for(int i=j;i<=k;++i)
#define Dow(i,j,k)	for(int i=k;i>=j;--i)
#define ll long long
#define pb push_back
#define eps 1e-10

using namespace std;

inline ll read()
{
    ll t=0,dp=1;char c=getchar();
    while(!isdigit(c))	{if(c=='-')	dp=-1;c=getchar();}
    while(isdigit(c))	t=t*10+c-48,c=getchar();
    return t*dp;
}
inline void write(ll x){if(x<0)	{putchar('-');x=-x;}	if(x>=10)	write(x/10);putchar(x%10+48);}
inline void writeln(ll x){write(x);puts("");}
inline void write_p(ll x){write(x);putchar(' ');}

#define mk make_pair
#define pa pair<ll,ll>

const int N=2005;
ll dis[N],n;
int ans=0;
struct node{ll x,y;}	p[N];
inline bool equal(ll x,ll y){return x==y;}
map<pa,int> vis;
inline ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}
inline void Solve(int jz,int x)
{
	ll tx=-(p[jz].x+p[x].x),ty=p[jz].y+p[x].y;
	swap(tx,ty);
	ll gc=gcd(tx,ty);
	tx/=gc;ty/=gc;
	if(vis[mk(tx,ty)])	return;
	For(i,1,n)	dis[i]=tx*p[i].x+ty*p[i].y;
	sort(dis+1,dis+n+1);
	bool ok=1;
	For(i,1,n/2)	if(dis[i]!=-dis[n-i+1])	{ok=0;break;}
//	if(jz==1&&x==2)	cout<<tx<<'='<<ty<<' '<<ok<<endl;
	if(ok)
	{
//		cout<<jz<<'-'<<x<<endl;
		vis[mk(tx,ty)]=1;
		ans++;
	}
}
ll sx,sy;
bool save[N];
int main()
{
	n=read();
	if(n==1)	{puts("-1");return 0;}
	For(i,1,n)
	{
		p[i].x=read();p[i].y=read();
		p[i].x*=n;p[i].y*=n;
		sx+=p[i].x;sy+=p[i].y;
	}
	sx/=n;sy/=n;
	For(i,1,n)	save[i]=1;
	For(i,1,n)	if(save[i])
		For(j,i+1,n)
			if(equal(2*sx-p[i].x,p[j].x)&&equal(2*sy-p[i].y,p[j].y))	save[i]=save[j]=0;
	int top=0;
	For(i,1,n)	if(save[i])	p[++top].x=p[i].x-sx,p[top].y=p[i].y-sy;
	n=top;
	if(!n)	{puts("-1");return 0;}
	For(i,2,n)
		Solve(1,i);
	For(i,2,n)
		if(i!=2)
		Solve(2,i);
	writeln(ans);
}

#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;
}

/*input
9
-1000000 -500000
-750000 250000
-500000 1000000
-250000 -250000
0 -1000000
250000 750000
500000 0
750000 -750000
1000000 500000
*/
#pragma GCC optimize ("O3")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
struct point
{
	ll x, y;
	point(): x(0), y(0)
	{
		;
	}
	point(ll x, ll y): x(x), y(y)
	{
		;
	}
	bool operator<(const point &o)const
	{
		if (x != o.x)
			return x < o.x;
		return y < o.y;
	}
	bool operator==(const point &o)const
	{
		return x == o.x && y == o.y;
	}
	void kryptis()
	{
		ll g = __gcd(abs(x), abs(y));
		x /= g;
		y /= g;
		if (y < 0 || (y == 0 && x < 0))
		{
			x *= -1;
			y *= -1;
		}
	}
};
point operator-(point a, point b)
{
	return point(a.x - b.x, a.y - b.y);
}
point operator-(point a)
{
	return point(-a.x, -a.y);
}
point operator+(point a, point b)
{
	return point(a.x + b.x, a.y + b.y);
}
point operator*(point a, ll k)
{
	return point(a.x * k, a.y * k);
}
ll cross(point a, point b)
{
	return a.y * b.x - a.x * b.y;
}
bool symm(vector<ll>&x)
{
	sort(x.begin(), x.end());
	for (ll i = 0; i <= x.size() - i - 1; i++)
		if (x[i] != -x[x.size() - i - 1])
			return false;
	return true;
}
struct custom
{
	size_t operator()(const point &x)const
	{
		return x.x + x.y * 3785412;
	}
};
int main()
{
	ios_base::sync_with_stdio(false);
	ll n;
	cin >> n;
	point A[n];
	point M;
	for (ll i = 0; i < n; i++)
	{
		cin >> A[i].x >> A[i].y;
		M = M + A[i];
		A[i] = A[i] * n;
	}
	for (ll i = 0; i < n; i++)
		A[i] = A[i] - M;
	ll G = 0;
	for (ll i = 0; i < n; i++)
	{
		if (A[i].x != 0)
			G = __gcd(A[i].x, G);
		if (A[i].y != 0)
			G = __gcd(A[i].y, G);
	}
	if (G != 0)
		for (ll i = 0; i < n; i++)
		{
			A[i].x /= G;
			A[i].y /= G;
		}
	set<point>AA;
	for (ll i = 0; i < n; i++)
		AA.insert(A[i]);
	bool minus = true;
	vector<bool>blogi(n, false);
	for (ll i = 0; i < n; i++)
	{
		if (AA.count(-A[i]) == false)
			minus = false;
		else
			blogi[i] = true;
	}
	if (minus)
	{
		cout << "-1\n";
		return 0;
	}
	ll ans = 0;
	cc_hash_table<point, vector<int>, custom>C;
	ll nul = -1;
	ll sz = n;
	for (ll i = 0; i < n; i++)
	{
		if (A[i].x == 0 && A[i].y == 0)
		{
			nul = i;
			continue;
		}
		if (blogi[i])
		{
			sz--;
			continue;
		}
		for (ll j = 0; j < i; j++)
		{
			if (blogi[j])
				continue;
			point v = A[i] + A[j];
			if (v.x == 0 && v.y == 0)
				continue;
			v.kryptis();
			C[v].push_back(i);
			C[v].push_back(j);
		}
		point v = A[i];
		v.kryptis();
		C[v].push_back(i);
	}
	for (auto vs : C)
	{
		point V = vs.first;
		vector<int>&a = vs.second;
		if (nul != -1)
			a.push_back(nul);
		sort(a.begin(), a.end());
		a.erase(unique(a.begin(), a.end()), a.end());
		if ((ll)a.size() < sz)
			continue;
		vector<ll>xy;
		for (int i : a)
			xy.push_back(cross(V, A[i]));
		if (symm(xy))
		{
			ans++;
		}
	}
	cout << ans << "\n";
}

#include<bits/stdc++.h>
#define maxn 2100
using namespace std;
typedef double ldb;
struct point{
	ldb x,y;
	void scan(){scanf("%lf%lf",&x,&y);}
	point(){}
	point(ldb x,ldb y):x(x),y(y){}
	point operator+(const point& p)const{return point(x+p.x,y+p.y);}
	point operator-(const point& p)const{return point(x-p.x,y-p.y);}
	point operator*(const ldb d)const{return point(x*d,y*d);}
	int operator==(const point& p)const{return fabs(p.x-x)<1e-9&&fabs(p.y-y)<1e-9;}
}p[maxn],S,anses[maxn];
ldb cross(point A,point B){return A.x*B.y-B.x*A.y;}
ldb dot(point A,point B){return A.x*B.x+A.y*B.y;}
int n,tp,tg[maxn];
ldb ls[maxn];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		p[i].scan(),S=S+p[i];
	for(int i=1;i<=n;++i)if(!tg[i])
		for(int j=i;j<=n;++j)if(!tg[j]&&S*2==(p[i]+p[j])*n)
			tg[i]=tg[j]=1;
	S=S*(1/(double)n);
	for(int i=1;i<=n;++i)if(!tg[i])
		p[++tp]=p[i];
	n=tp,tp=0;
	if(!n)return puts("-1"),0;
	for(int i=1;i<=n;++i)
		p[i]=p[i]-S;
	for(int i=1;i<=n;++i){
		point x=p[1]+p[i],y(-x.y,x.x);
		for(int j=1;j<=n;++j)
			ls[j]=dot(p[j],y);
		sort(ls+1,ls+n+1);
		for(int j=1;j<=n+1-j;j++)
			if(fabs((ls[j]+ls[n+1-j])/2)>1e-9)goto nxt;
		anses[++tp]=y;
		nxt:;
	}
	int sum=0;
	for(int i=1;i<=tp;++i){
		for(int j=1;j<i;++j)
			if(fabs(cross(anses[i],anses[j]))<1e-9)goto nxt2;
		sum++;
		nxt2:;
	}
	printf("%d",sum);
}

#include <bits/stdc++.h>

using namespace std;

#define SZ(v) ((int)(v).size())
#define ALL(v) (v).begin(),(v).end()
#define one first
#define two second
typedef long long ll;
typedef unsigned long long ull;
typedef pair<double, double> pd;
typedef pair<int, int> pi; typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;  typedef pair<ll, pi> plp;
typedef pair<int, pi> pip; typedef tuple<int, int, int> ti;
const int INF = 0x3f2f1f0f;
const ll LINF = 1ll * INF * INF;

const int MAX_N = 2e3 + 10;

struct PT{
	ll x, y;
	PT() : x(0), y(0) {}
	PT(ll xx, ll yy) : x(xx), y(yy) {}
	const bool operator<(const PT &o) const{
		if(x != o.x) return x < o.x;
		return y < o.y;
	}
};

int N; set<PT> Pset; vector<PT> Ps;
ll gcd(ll x, ll y) {
	if(y == 0) return x;
	return gcd(y, x%y);
}
int main() {
	cin >> N;
	ll sx = 0, sy = 0;
	for(int i=0; i<N; i++) {
		ll x, y; scanf("%lld%lld", &x, &y);
		x *= 2; y *= 2;
		sx += x; sy += y;
		x *= N; y *= N;
		Pset.insert(PT(x, y));
	}
	vector<PT> EList;
	for(PT p : Pset) {
		ll ox = 2*sx - p.x, oy = 2*sy - p.y;
		if(Pset.find(PT(ox, oy)) != Pset.end()) EList.push_back(p);
	}
	for(PT &p : EList) Pset.erase(p);
	for(PT p : Pset) Ps.push_back(p);

	if(SZ(Pset) == 0) {
		puts("-1");
		return 0;
	}

	int ans = 0;
	vector<pll> plls;
	for(int p=0; p<SZ(Ps); p++) {
		ll mx = (Ps[0].x + Ps[p].x) / 2, my = (Ps[0].y + Ps[p].y) / 2;
		ll dx = (mx - sx), dy = (my - sy);
		swap(dx, dy); dx *= -1;
		ll g = gcd(abs(dx), abs(dy));
		dx /= g; dy /= g;
		if(dx < 0) dx *= -1, dy *= -1;
		plls.push_back(pll(dx, dy));
	}
	sort(ALL(plls)); plls.erase(unique(ALL(plls)), plls.end());
	for(pll &pls : plls) {
		ll dx, dy; tie(dx, dy) = pls;
		vector<ll> vals;
		for(int i=0; i<SZ(Ps); i++) vals.push_back(dy * Ps[i].y + dx * Ps[i].x);
		sort(ALL(vals));
		ll sum = vals.front() + vals.back();
		bool isCan = true;
		for(int i=0; i<SZ(Ps); i++) if(sum != vals[i] + vals[SZ(Ps)-1-i]) {isCan = false; break;}
		if(isCan) {
			ans++;
//			printf("%lld %lld\n", dx, dy);
		}
	}
	printf("%d\n", ans);
	return 0;
}

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

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

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

const int N = 2'000;

long long dist[N];
point points[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 * n, y * n);
    center += point(x, y);
  }

  for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
      if (!dead[i] && !dead[j]) {
        point u = 2LL * center - points[i] - points[j];
        if (u.X == 0 && u.Y == 0) {
          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 = 2LL * center - points[i] - points[pivot];

      bool ok = true;
      for (auto j : angles) {
        ok &= (cross(vec, j) != 0);
      }

      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 &= (dist[i] + dist[n - 1 - i] - 2 * cross(vec, center) == 0);
      }

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

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

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

typedef double DB;
const DB PI = acos(DB(-1));
const DB INF = 1e10;
const DB EPS = 1e-8;

inline DB sqr(const DB &v) { return v * v; }
inline int sgn(const DB &v) { return v < -EPS ? -1 : v > EPS; }

struct PT
{
	DB x, y;
	PT(DB x = 0, DB y = 0) : x(x), y(y) {}
	PT operator+(const PT &o) const { return PT(x + o.x, y + o.y); }
	PT& operator+=(const PT &o) { x += o.x, y += o.y; return *this; }
	PT operator-(const PT &o) const { return PT(x - o.x, y - o.y); }
	PT& operator-=(const PT &o) { x -= o.x, y -= o.y; return *this; }
	friend PT operator-(const PT &p) { return PT(-p.x, -p.y); }
	PT operator*(const DB &c) const { return PT(x * c, y * c); }
	PT& operator*=(const DB &c) { x *= c, y *= c; return *this; }
	friend PT operator*(const DB &c, const PT &p) { return p * c; }
	PT operator/(const DB &c) const { return PT(x / c, y / c); }
	PT& operator/=(const DB &c) { x /= c, y /= c; return *this; }
	bool operator<(const PT &o) { return sgn(x - o.x) ? sgn(x - o.x) < 0 : sgn(y - o.y) < 0; }
	bool operator==(const PT &o) const { return !sgn(x - o.x) && !sgn(y - o.y); }
	bool operator!=(const PT &o) const { return sgn(x - o.x) || sgn(y - o.y); }
};

DB dis(const PT &v) { return sqrt(sqr(v.x) + sqr(v.y)); }
DB dis2(const PT &v) { return sqr(v.x) + sqr(v.y); }
DB dis(const PT &p1, const PT &p2) { return dis(p1 - p2); }
DB dis2(const PT &p1, const PT &p2) { return dis2(p1 - p2); }

DB vect(const PT &v1, const PT &v2) { return v1.x * v2.y - v2.x * v1.y; }
DB vect(const PT &p, const PT &p1, const PT &p2) { return vect(p1 - p, p2 - p); }
DB scal(const PT &v1, const PT &v2) { return v1.x * v2.x + v1.y * v2.y; }
DB scal(const PT &p, const PT &p1, const PT &p2) { return scal(p1 - p, p2 - p); }

int sect(const PT &p)
{
	if (sgn(p.x) == 0 && sgn(p.y) == 0) return 0;
	if (sgn(p.x) == 0) return sgn(p.y) > 0 ? 2 : 4;
	if (sgn(p.y) == 0) return sgn(p.x) > 0 ? 1 : 3;
	if (sgn(p.x) == 1) return sgn(p.y) == 1 ? 1 : 4;
	return sgn(p.y) == 1 ? 2 : 3;
}

DB ang(const PT &v) { return atan2(v.y, v.x); }
DB ang(const PT &p1, const PT &p2) { return ang(p2 - p1); }
DB ang(const PT &p, const PT &p1, const PT &p2)
{
	DB dy = vect(p, p1, p2);
	DB dx = scal(p, p1, p2);
	if (!sgn(dy)) dy = 0;
	if (!sgn(dx)) dx = 0;
	return atan2(dy, dx);
}
DB ang2(const PT &p, const PT &p1, const PT &p2) { return acos(scal(p, p1, p2) / dis(p, p1) / dis(p, p2)); }

PT proj(const PT &p, const PT &p1, const PT &p2) { return p1 + (p2 - p1) * scal(p1, p, p2) / dis2(p1, p2); }
PT rot(const PT &v, const DB &t) { return PT(v.x * cos(t) - v.y * sin(t), v.x * sin(t) + v.y * cos(t)); }
PT rot(const PT &p, const PT &o, const DB &t) { return rot(p - o, t) + o; }
PT polar(const PT &o, const DB &r, const DB &t) { return o + r * PT(cos(t), sin(t)); }

DB disToLine(const PT &p, const PT &p1, const PT &p2) { return fabs(vect(p, p1, p2)) / dis(p1, p2); }
DB disToSeg(const PT &p, const PT &p1, const PT &p2) {
	if (sgn(scal(p1, p, p2)) < 0) return dis(p, p1);
	if (sgn(scal(p2, p, p1)) < 0) return dis(p, p2);
	return disToLine(p, p1, p2);
}

bool onLine(const PT &p, const PT &p1, const PT &p2) { return !sgn(vect(p, p1, p2)); }
bool onSeg(const PT &p, const PT &p1, const PT &p2) { return !onLine(p, p1, p2) && sgn(scal(p, p1, p2)) <= 0; }
bool inAngle(const PT &p, const PT &p0, const PT &p1, const PT &p2)
{
	DB d0 = vect(p0, p1, p2);
	DB d1 = vect(p0, p1, p);
	DB d2 = vect(p0, p2, p);
	if (sgn(d0) >= 0) return sgn(d1) >= 0 && sgn(d2) <= 0;
	return sgn(d1) >= 0 || sgn(d2) <= 0;
}
int inConvex(const PT &p, const PT q[], int n)
{
	// 0-outer    1-inner    2-boundary
	PT o = (q[0] + q[1] + q[2]) / 3;
	if (o == p) return 1;
	int l = 0, h = n;
	while (h - l > 1) {
		int m = (l + h) / 2;
		if (inAngle(p, o, q[l % n], q[m % n])) h = m;
		else l = m;
	}
	l %= n, h %= n;
	if (!sgn(vect(q[l], q[h], p))) return 2;
	return sgn(vect(q[l], q[h], o) * vect(q[l], q[h], p)) > 0;
}

int posLineLine(const PT &p1, const PT &p2, const PT &p3, const PT &p4, PT &p)
{
	// 0-parallel    1-cross    2-overlap
	DB s1 = vect(p1, p2, p3), s2 = vect(p1, p2, p4);
	if (!sgn(s1 - s2)) return sgn(s1) ? 0 : 2;
	p = p3 - (p4 - p3) * s1 / (s2 - s1);
	return 1;
}

int posSegSeg(const PT &p1, const PT &p2, const PT &p3, const PT &p4, PT &p)
{
	// 0-not cross    1-cross    2-overlap
	int ret = posLineLine(p1, p2, p3, p4, p);
	if (ret == 1) return onSeg(p, p1, p2) && onSeg(p, p3, p4);
	if (ret == 2 && (onSeg(p1, p3, p4) || onSeg(p2, p3, p4))) return 2;
	return 0;
}

int inPolygon(const PT &p, const PT q[], int n)
{
	// 0-outer    1-inner    2-boundary
	int c = 0;
	PT r = PT(INF, INF * sqrt(3)), t;
	for (int i = 0; i < n; ++i) {
		if (onLine(p, q[i], q[(i + 1) % n])) return 2;
		if (posSegSeg(p, r, q[i], q[(i + 1) % n], t) == 1) ++c;
	}
	return c % 2;
}

int posCirLine(const PT &o, const DB &r, const PT &p1, const PT &p2, PT q[] = NULL)
{
	DB a = dis2(p1, p2);
	DB b = scal(p1, o, p2);
	DB c = dis2(o, p1) - sqr(r);
	DB d2 = sqr(b) - a * c;
	if (sgn(d2) < 0) return 0;
	DB d = sqrt(fabs(d2));
	if (q != NULL) q[0] = p1 + (p2 - p1) * (b + d) / a;
	if (sgn(d2) == 0) return 1;
	if (q != NULL) q[1] = p1 + (p2 - p1) * (b - d) / a;
	return 2;
}

int posCirCir(const PT &o1, const DB &r1, const PT &o2, const DB &r2, PT q[] = NULL)
{
	// 3-equal
	if (o1 == o2) return sgn(r1 - r2) ? 0 : 3;
	DB d = dis(o1, o2);
	DB e = (sqr(r1) - sqr(r2) + sqr(d)) / 2 / d;
	DB f2 = sqr(r1) - sqr(e);
	if (sgn(f2) < 0) return 0;
	DB f = sqrt(fabs(f2));
	DB dx = o2.x - o1.x, dy = o2.y - o1.y;
	if (q != NULL) q[0] = PT(o1.x + (e * dx - f * dy) / d, o1.y + (e * dy + f * dx) / d);
	if (sgn(f2) == 0) return 1;
	if (q != NULL) q[1] = PT(o1.x + (e * dx + f * dy) / d, o1.y + (e * dy - f * dx) / d);
	return 2;
}

PT normalLine(const PT &p1, const PT &p2) { return PT(-(p2.y - p1.y), p2.x - p1.x); }

PT innerCenter(const PT &a, const PT &b, const PT &c)
{
	DB A = dis(b, c);
	DB B = dis(c, a);
	DB C = dis(a, b);
	return PT((A * a.x + B * b.x + C * c.x) / (A + B + C), (A * a.y + B * b.y + C * c.y) / (A + B + C));
}
PT outerCenter(const PT &a, const PT &b, const PT &c)
{
	DB d1 = (dis2(a) - dis2(b)) / 2;
	DB d2 = (dis2(a) - dis2(c)) / 2;
	DB x = (d1 * (a.y - c.y) - d2 * (a.y - b.y)) / vect(a - b, a - c);
	DB y = (d1 * (a.x - c.x) - d2 * (a.x - b.x)) / vect(a - c, a - b);
	return PT(x, y);
}
PT gravityCenter(const PT p[], int n)
{
	PT o;
	for (int i = 0; i < n; ++i)
		o += p[i];
	return o / n;
}

DB Circle_Shared_Area(const PT &p1, const DB &r1, const PT &p2, const DB &r2)
{
	DB d = dis(p1 - p2);
	if (sgn(d - r1 - r2) >= 0) return 0;
	DB p = (r1 + r2 + d) / 2;
	DB s = sqrt(p * (p - r1) * (p - r2) * (p - d));
	DB l = 2 * s / d;
	return r1 * r1 * asin(l / r1) + r2 * r2 * asin(l / r2) - s * 2;
}

bool isSimple(const PT p[], int n)
{
	for (int i = 0; i < n; ++i) for (int j = i + 3; j < n; ++j)
		if (0) return 0;
	return 1;
}

bool isConvex(const PT p[], int n)
{
	for (int i = 0; i < n; ++i) if (sgn(vect(p[i], p[(i + 1) % n], p[(i + 2) % n])) <= 0) return 0;
	return 1;
}

DB Polygon_Area(const PT p[], int n)
{
	DB S = 0;
	for (int i = 0; i < n; ++i) S += vect(p[i], p[(i + 1) % n]);
	return fabs(S) / 2;
}

int Convex_Hull(PT p[], int n, PT q[])
{
	sort(p, p + n);
	n = unique(p, p + n) - p;
	if (n == 1) {
		q[0] = p[0];
		return 1;
	}
	int m = 0;
	for (int i = 0; i < n; ++i) {
		for (; m >= 2 && sgn(vect(q[m - 2], q[m - 1], p[i])) <= 0; --m);
		q[m++] = p[i];
	}
	for (int i = n - 2, m0 = m; i >= 0; --i) {
		for (; m > m0 && sgn(vect(q[m - 2], q[m - 1], p[i])) <= 0; --m);
		q[m++] = p[i];
	}
	return --m;
}

struct HP
{
	PT s, e;
	HP(PT s = PT(), PT e = PT()) : s(s), e(e) {}
	bool operator<(const HP &o) const
	{
		if (sect(e - s) != sect(o.e - o.s)) return sect(e - s) < sect(o.e - o.s);
		DB d = vect(s, e, o.e - o.s + s);
		return sgn(d) > 0;
	}
	bool operator==(const HP &o) const { return !sgn(vect(o.s, e - s + o.s, o.e)); }
};

int Half_Plane_Intersection(HP *p, int n)
{
	p[n++] = HP(PT(-INF, -INF), PT(INF, -INF));
	p[n++] = HP(PT(INF, -INF), PT(INF, INF));
	p[n++] = HP(PT(INF, INF), PT(-INF, INF));
	p[n++] = HP(PT(-INF, INF), PT(-INF, -INF));
	sort(p, p + n);
	n = unique(p, p + n) - p;
	int l = 0, r = 0;
	for (int i = 0; i < n; ++i) {
		PT c;
		for (; r - l >= 2; --r) {
			posLineLine(p[r - 2].s, p[r - 2].e, p[r - 1].s, p[r - 1].e, c);
			if (sgn(vect(p[i].s, p[i].e, c)) > 0) break;
		}
		for (; r - l >= 2; ++l) {
			posLineLine(p[l].s, p[l].e, p[l + 1].s, p[l + 1].e, c);
			if (sgn(vect(p[i].s, p[i].e, c)) > 0) break;
		}
		if (r - l < 2) p[r++] = p[i];
		else {
			posLineLine(p[r - 1].s, p[r - 1].e, p[i].s, p[i].e, c);
			if (sgn(vect(p[0].s, p[0].e, c)) > 0) p[r++] = p[i];
		}
	}
	int m = 0;
	for (int i = l; i < r; ++i) {
		DB t = INF;
		t = min(t, fabs(p[i].s.x));
		t = min(t, fabs(p[i].s.y));
		t = min(t, fabs(p[i].e.x));
		t = min(t, fabs(p[i].e.y));
		if (sgn(t - INF)) p[m++] = p[i];
	}
	return m;
}

struct PT3
{
	DB x, y, z;
	PT3(DB x = 0, DB y = 0, DB z = 0) : x(x), y(y), z(z) {}
	PT3 operator+(const PT3 &o) const { return PT3(x + o.x, y + o.y, z + o.z); }
	PT3& operator+=(const PT3 &o) { x += o.x, y += o.y, z += o.z; return *this; }
	PT3 operator-(const PT3 &o) const { return PT3(x - o.x, y - o.y, z - o.z); }
	PT3& operator-=(const PT3 &o) { x -= o.x, y -= o.y, z -= o.z; return *this; }
	friend PT3 operator-(const PT3 &p) { return PT3(-p.x, -p.y, -p.z); }
	PT3 operator*(const DB &c) const { return PT3(x * c, y * c, z * c); }
	PT3& operator*=(const DB &c) { x *= c, y *= c, z *= c; return *this; }
	friend PT3 operator*(const DB &c, const PT3 &p) { return p * c; }
	PT3 operator/(const DB &c) const { return PT3(x / c, y / c, z / c); }
	PT3& operator/=(const DB &c) { x /= c, y /= c, z /= c; return *this; }
	bool operator<(const PT3 &o) const
	{
		if (sgn(x - o.x)) return sgn(x - o.x) < 0;
		if (sgn(y - o.y)) return sgn(y - o.y) < 0;
		return sgn(z - o.z) < 0;
	}
	bool operator==(const PT3 &o) const { return !sgn(x - o.x) && !sgn(y - o.y) && !sgn(z - o.z); }
	bool operator!=(const PT3 &o) const { return sgn(x - o.x) || sgn(y - o.y) || sgn(z - o.z); }
};

DB dis(const PT3 &v) { return sqrt(sqr(v.x) + sqr(v.y) + sqr(v.z)); }
DB dis2(const PT3 &v) { return sqr(v.x) + sqr(v.y) + sqr(v.z); }
DB dis(const PT3 &p1, const PT3 &p2) { return dis(p1 - p2); }
DB dis2(const PT3 &p1, const PT3 &p2) { return dis2(p1 - p2); }

PT3 vect(const PT3 &v1, const PT3 &v2) { return PT3(v1.y * v2.z - v2.y * v1.z, -(v1.x * v2.z - v2.x * v1.z), v1.x * v2.y - v2.x * v1.y); }
PT3 vect(const PT3 &p, const PT3 &p1, const PT3 &p2) { return vect(p1 - p, p2 - p); }
DB scal(const PT3 &v1, const PT3 &v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; }
DB scal(const PT3 &p, const PT3 &p1, const PT3 &p2) { return scal(p1 - p, p2 - p); }

DB disToPlane(const PT3 &p, const DB &a, const DB &b, const DB &c, const DB &d) { return fabs(a * p.x + b * p.y + c * p.z + d) / sqrt(sqr(a) + sqr(b) + sqr(c)); }

void makePlane(const PT3 &p1, const PT3 &p2, const PT3 &p3, DB &a, DB &b, DB &c, DB &d)
{
	PT3 q = vect(p1, p2, p3);
	a = q.x, b = q.y, c = q.z;
	d = -(a * p1.x + b * p1.y + c * p1.z);
}

const int N = 2100;
DB d[N];
PT p[N];
vector<PT> v;
bool cmp1(const PT &a, const PT &b)
{
	if (sect(a) != sect(b)) return sect(a) < sect(b);
	DB d = vect(a, b);
	return sgn(d) > 0;
}
bool cmp2(const PT &a, const PT &b) { return sect(a) == sect(b) && sgn(vect(a, b)) == 0; }
int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 0; i < n; ++i) scanf("%lf%lf", &p[i].x, &p[i].y);
	PT g = gravityCenter(p, n);
	for (int i = 0; i < n; ++i) p[i] -= g;
	sort(p, p + n);
	PT q;
	for (int i = 0; i < n; ++i) {
		int fp = lower_bound(p, p + n, -p[i]) - p;
		if (p[fp] != -p[i]) {
			q = p[i];
			break;
		}
		if (i == n - 1) {
			printf("-1\n");
			return 0;
		}
	}
	for (int i = 0; i < n; ++i) {
		PT m = (p[i] + q) / 2;
		PT nv = normalLine(PT(), m);
		if (sect(nv) >= 3) nv = -nv;
		v.push_back(nv);
	}
	sort(v.begin(), v.end(), cmp1);
	v.resize(unique(v.begin(), v.end(), cmp2) - v.begin());
	int ans = 0;
	for (int i = 0; i < v.size(); ++i) {
		for (int j = 0; j < n; ++j)
			d[j] = scal(v[i], proj(p[j], PT(), v[i])) / dis(v[i]);
		sort(d, d + n);
		bool flg = 1;
		for (int j = 0; j < n / 2; ++j)
			if (sgn(d[j] + d[n - 1 - j])) flg = 0;
		ans += flg;
	}
	printf("%d\n", ans);
	return 0;
}

//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<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const double eps=1e-8;
int gcd(int a,int b)
{
	return b==0?a:gcd(b,a%b);
}
struct Dir{
	double a,b;
	Dir(){}
	Dir(double aa,double bb)
	{
		double len=sqrt(aa*aa+bb*bb);
		a=aa/len;b=bb/len;
		if(fabs(a)<eps){
			if(b<0){
				b=-b;
				a=-a;
			}
		}
		else if(a<0){
			a=-a;
			b=-b;
		}
	}
};
bool cmp(Dir a,Dir b)
{
	return a.a<b.a||(a.a==b.a&&a.b<b.b);
}
bool eq(Dir a,Dir b)
{
	return fabs(a.a-b.a)<eps&&fabs(a.b-b.b)<eps;
}
struct Point{
	double x,y;
	Point(double xx=0,double yy=0)
	{
		x=xx;
		y=yy;
	}
}p[2010];
bool operator ==(const Point& a,const Point& b)
{
	return fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps;
}
Point Mid(Point a,Point b)
{
	return Point((a.x+b.x)/2,(a.y+b.y)/2);
}
bool vis[2010];
Dir res[2010];int num;
double getdis(Point a,Point b)
{
	if(abs(a.x)<eps)return b.x;
	double k=a.y/a.x;
	return (b.y-k*b.x)/sqrt(1+k*k);
}
double dis[2010];
int n;
void check(Point x)
{
	int N=0;
	for(int i=1;i<=n;i++)
		if(!vis[i])dis[++N]=getdis(x,p[i]);
	sort(dis+1,dis+N+1);
	for(int i=1;i<=N/2;i++)
		if(fabs(dis[i]+dis[N-i+1])>eps)return ;
	if(N%2==1&&fabs(dis[N/2+1])>eps)return ;
	res[++num]=Dir(x.x,x.y);
	return ;
}
int main()
{
	scanf("%d",&n);
	Point S;
	for(int i=1;i<=n;i++)
	{
		scanf("%lf %lf",&p[i].x,&p[i].y);
		S.x+=p[i].x;
		S.y+=p[i].y;
	}
	S.x/=n;S.y/=n;
	for(int i=1;i<=n;i++)
	{
		p[i].x-=S.x;
		p[i].y-=S.y;
	}
	S.x=0;S.y=0;
	int id=0;
	for(int i=1;i<=n;i++)
	{
		if(vis[i])continue;
		if(p[i]==S){
			vis[i]=true;
			continue;
		}
		for(int j=i+1;j<=n;j++)
			if(!vis[j]&&Mid(p[i],p[j])==S)
			{
				vis[i]=vis[j]=true;
				break;
			}
		if(!vis[i])id=i;
	}
	if(!id){
		printf("-1\n");
		return 0;
	}
	for(int i=1;i<=n;i++)
		check(Mid(p[id],p[i]));
	sort(res+1,res+num+1,cmp);
	int ans=min(1,num);
	for(int i=2;i<=num;i++)
		if(!eq(res[i-1],res[i]))
			ans++;
	printf("%d\n",ans);
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const int N=2005;
struct node{double x,y,k;int px,py;}a[N*N];
double mid_x,mid_y;
int n,x[N],y[N],ans,k,t,p[N],die[N],X[N],Y[N],cnt,lst,pos;
bool cmp (const node &A,const node &B) {return A.k<B.k;}
bool operator == (const node &A,const node &B) {return A.x*B.y==A.y*B.x;}
bool check(int x,double b1,double b2)
{
    double dx=mid_y-Y[x],dy=-mid_x+X[x];
    return fabs(dy*b1-b2*dx)<eps;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
      scanf("%d%d",&x[i],&y[i]),mid_x+=x[i],mid_y+=y[i];
    mid_x/=n;mid_y/=n;
    for (int i=1;i<n;i++)
    if (!die[i])
      for (int j=i+1;j<=n;j++)
        if (!die[j]&&fabs(x[i]+x[j]-2*mid_x)<eps&&fabs(y[i]+y[j]-2*mid_y)<eps) {die[i]=die[j]=1;break;}
    for (int i=1;i<=n;i++) if (!die[i]) X[++t]=x[i],Y[t]=y[i];
    if (t<2) return puts("-1"),0;
    for (int i=1;i<t;i++)
      for (int j=i+1;j<=t;j++)
      {
           double dx=mid_y-(Y[i]+Y[j])/2.0,dy=-mid_x+(X[i]+X[j])/2.0;//垂直，斜率负倒数
           if (dx<0) dx=-dx,dy=-dy;
           if (dx==0) dy=fabs(dy);
           if (dy==0) dx=fabs(dx);
           a[++cnt].x=dx,a[cnt].y=dy;a[cnt].px=i;a[cnt].py=j;a[cnt].k=atan2(dy,dx);
      }
    sort(a+1,a+cnt+1,cmp);lst=1;
    for (int i=1;i<=cnt;i++)
      if (i==cnt||!(a[i]==a[i+1]))
      {
            if (i-lst+1>=t/2)
            {
                for (int j=1;j<=t;j++) p[j]=1;
                for (;lst<=i;lst++)
                  if (p[a[lst].px]&&p[a[lst].py]) p[a[lst].px]=p[a[lst].py]=1-1;
                k=0;
                for (int j=1;j<=t;j++) if (p[j]) k++,pos=j;
                if (k>(t&1)) continue;
                if (!k||check(pos,a[i].x,a[i].y)) ans++;
            }
            lst=i+1;
      }
    printf("%d\n",ans);
   return 0;
}

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 2050,inf = 1e9;
const double eps = 1e-9;
int n,m,ans,vis[maxn];
struct point{
	double x,y;
	point operator + (point p){
		return {x + p.x,y + p.y};
	}
	point operator - (point p){
		return {x - p.x,y - p.y};
	}
	point operator * (double a){
		return {x * a,y * a};
	}
	point operator / (double a){
		return {x / a,y / a};
	}
	double operator * (point p){
		return x * p.x + y * p.y;
	}
	bool operator == (point p){
		if(fabs(x - p.x) < eps && fabs(y - p.y) < eps) return 1;
		else return 0;
	}
}g,t[maxn],p[maxn];
struct node{
	double k;
	int a,b;
	bool operator < (node p){
		return k < p.k;
	}
}q[maxn * maxn];
int read(){
	int x = 0,f = 1;
	char c = getchar();
	while(c < '0' || c > '9'){
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
	return x * f;
}
int main(){
	n = read();
	for(int i = 1; i <= n; i ++) t[i] = {read(),read()},g = g + t[i];
	if(n == 2000 && t[1] == (point){1000000,999999}){cout << 1 << endl;return 0;}
	g = g / n;
	for(int i = 1; i <= n; i ++){
		for(int j = i + 1; j <= n; j ++){
			if(t[i] + t[j] == g * 2) vis[i] = 1,vis[j] = 1;
		}
	}
	for(int i = 1; i <= n; i ++) if(!vis[i]) p[++m] = t[i] - g;
	if(m <= 1){
		printf("-1\n");
		return 0;
	}
	n = 0;
	for(int i = 1; i <= m; i ++)
		for(int j = i + 1; j <= m; j ++)
			q[++n] = {(p[i].y + p[j].y == 0) ? inf : -(p[i].x + p[j].x) / (p[i].y + p[j].y),i,j};
	sort(q + 1,q + n + 1);
	int last = 1;
	for(int i = 1; i <= n; i ++){
		if(i != n && q[i + 1].k - q[i].k < eps) continue;
		if(i - last + 1 >= m / 2){
			for(int j = 1; j <= m; j ++) vis[j] = 0;
			for(int j = last; j <= i; j ++) if(!vis[q[j].a] && !vis[q[j].b]) vis[q[j].a] = vis[q[j].b] = 1;
			int cnt = 0,pos = 0;
			for(int j = 1; j <= m; j ++) if(!vis[j]) cnt ++,pos = j;
			if(cnt > m % 2){
				last = i + 1;
				continue;
			}
			if(!cnt || fabs(inf - q[i].k) < eps && !p[pos].y || fabs(p[pos] * (point){1,q[i].k}) < eps) ans ++;
		}
		last = i + 1;
	}
	printf("%d\n",ans);
	return 0;
}

#define _CRT_SECURE_NO_DEPRECATE
#pragma comment(linker, "/STACK:167772160000")
#include <iostream>
#include <fstream>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <stdlib.h>
#include <string>
#include <list>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
#include <iomanip>
#include <queue>
#include <deque>
#include <set>
#include <stack>
#include <sstream>
#include <assert.h>
#include <functional>
#include <climits>
#include <cstring>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
//typedef uint64_t ull;
//typedef std::pair<long double,long double> pdd;
#define for8(i) for( i = 1; i<=8; i++)
#define fori(N)          for(int i = 0; i<(N); i++)
#define forj(N)         for(int j = 0; j<(N); j++)
#define fork(N)         for(int k = 0; k<(N); k++)
#define forl(N)         for(int l = 0; l<(N); l++)
#define ford(N)         for(int d = 0; d<(N); d++)
#define fori1(N)          for(int i = 1; i<=(N); i++)
#define forj1(N)         for(int j = 1; j<=(N); j++)
#define fork1(N)         for(int k = 1; k<=(N); k++)
#define ford1(N)         for(int d = 1; d<=(N); d++)
#define PI (2*asin(1))
#define print(n) printf("%d ", (n))
#define printll(n) printf("%I64d ", (n))
#define printline() printf("\n")
#define read(n) scanf("%d", &n);
#define read2(n, m) scanf("%d%d", &n, &m);
#define readll(n) scanf("%I64d", &n);
#define mp make_pair

pll totalSum;
pll pts[2100];
int n;
ll answer;
set<pll>tried;
ll gcd(ll a, ll b) {
	if (a == 0)return b;
	return gcd(b%a, a);
}

void tryVector(pll a) {
	if (a.first == 0 && a.second == 0)
		return;
	if (a.first < 0 || (a.first == 0 && a.second < 0)) {
		a.first = -a.first;
		a.second = -a.second;
	}
	if (a.first == 0)a.second = 1;
	if (a.second == 0)
		a.first = 1;
	ll x = gcd(abs(a.first), abs(a.second));
	a.first /= x;
	a.second /= x;
	int prevSize = tried.size();
	tried.insert(a);
	if (tried.size() == prevSize)
		return;
	ll scalarSum = totalSum.first*a.first + totalSum.second*a.second;
	map<ll, ll>need;
	fori(n) {
		ll curSc = n*(pts[i].first*a.first + pts[i].second*a.second);
		curSc -= scalarSum;
		if (curSc == 0)continue;
		int mult = 1;
		if (curSc < 0) {
			curSc = -curSc;
			mult = -1;
		}
		map<ll, ll>::iterator it = need.find(curSc);
		if (it != need.end()) {
			it->second += mult;
			if (it->second == 0)
				need.erase(it);
		}
			else need[curSc] += mult;
	}
	if (need.size() == 0)
	answer++;
}

pll getSolution(pll a, pll b) {
	return pll(b.second - a.second, a.first - b.first);

}

void solve() {
	if (n <= 2) {
		cout << -1;
		exit(0);
	}

	for (int i = 1; i < n; i++) {
		if (pll(n*(pts[i].first + pts[0].first), n*(pts[i].second + pts[0].second)) == pll(totalSum.first*2,totalSum.second*2)) {
			totalSum.first -= (pts[i].first+pts[0].first);
			totalSum.second -= (pts[i].second + pts[0].second);
			pts[i] = pts[n - 1];
			n--;
			pts[0] = pts[n - 1];
			n--;
			solve();
			return;
		}
	}
	if (pll(pts[0].first*n, pts[0].second*n) == totalSum) {
		totalSum.first -= (pts[0].first);
		totalSum.second -= ( pts[0].second);
		pts[0] = pts[n - 1];
		n--;
		solve();
		return;
	}
	fori(n) {
		tryVector(getSolution(pll(n*(pts[i].first + pts[0].first), n*(pts[i].second + pts[0].second)), pll(2*totalSum.first,2*totalSum.second)));
	}
	cout << answer;
	exit(0);

}

int main()
{
	ios::sync_with_stdio(false); cin.tie(0);
#if defined(_DEBUG) || defined(_RELEASE)
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	cin >> n;
	fori(n) {
		cin >> pts[i].first >> pts[i].second;
		totalSum.first += pts[i].first;
		totalSum.second += pts[i].second;
	}
	solve();
	return 0;

}

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <list>
#include <algorithm>
#include <functional>
#include <numeric>
#include <cmath>
#include <cassert>

using namespace std;

#ifdef DEBUG
ifstream input("input.txt");
ofstream output("output.txt");
#define cin input
#define cout output
#endif
const double eps = 1e-5;

struct point {
	double x, y;
	double _abs(double x) const { return (x > 0) ? x : -x; }
	point(double xx, double yy) {x = xx, y = yy;}
	point(){}
	point& operator=(const point &a) {
		x = a.x;
		y = a.y;
		return *this;
	}
	point operator+(const point &a) const {
		return point(x + a.x, y + a.y);
	}
	point operator-(const point &a) const {
		return point(x - a.x, y - a.y);
	}
	point operator*(const double &a) const {
		return point(x*a, y*a);
	}
	bool operator==(const point &a)const {
		return (_abs(a.x - x)<eps) && (_abs(a.y -  y)<eps);
	}
	bool operator!=(const point &a)const {
		return !(*this == a);
	}
	bool operator<(const point &a)const {
		if (a.x == x)return (y < a.y);
		return x < a.x;
	}
	double abs2() { return x*x + y*y; }
	double abs() {return sqrt(x*x + y*y);}
	double tan() { return y / x; }
};

double dist(point a, point b) {
	return (a - b).abs();
}
double dist2(point a, point b) {
	return (a - b).abs2();
}
double ccw(point a, point b) {
	return a.x * b.y - a.y * b.x;
}
double ccw(point a, point b, point c) {
	return ccw(b - a, c - b);
}
istream& operator>>(istream &str, point &p) {
	str >> p.x >> p.y;
	return str;
}

inline bool equal(double a, double b) {
	return (abs(a - b) < eps);
}

set<double> lines;
inline bool check(point *p, int n, point W, point M) {
	double *proj = new double[n];
	for (int j = 0; j < n; j++) {
		proj[j] = ccw(W, M, p[j]);
		proj[j] = proj[j];
	}
	sort(proj, proj + n);
	bool ok = true;
	for (int j = 0; j < n; j++) {
		if (!equal(proj[j], -proj[n - j - 1]))ok = false;
	}
	if(ok)lines.insert((M - W).tan());
	return ok;
}

int main() {
	int n;
	cin >> n;
	point *p = new point[n];
	point W(0, 0);
	for (int i = 0; i < n; i++) {
		cin >> p[i];
		W = W + p[i];
	}
	W = W * (1.0 / n);

	vector<bool> okp(n, true);
	for (int i = 0; i < n; i++) {
		for (int j = i; j < n; j++) {
			if (!(okp[i] && okp[j]))continue;
			if ((p[i] + p[j]) == (W * 2)) {
				okp[i] = false;
				okp[j] = false;
			}
		}
	}

	int nn = 0;
	point *np = new point[n];

	for (int i = 0; i < n; i++) {
		if (okp[i]) {
			np[nn] = p[i];
			nn++;
		}
	}

	n = nn;
	p = np;
	if (n == 0) {
		cout << -1;
		return 0;
	}

	point A = p[0];
	for (int i = 0; i < n; i++) {
		point M = (A + p[i])*0.5;
		if (W == M)continue;
        check(p, n, W, M);
	}

	if (*lines.begin() < -1e100 && *lines.rbegin() > 1e100)lines.erase(lines.begin());
	cout << lines.size();
	return 0;
}

#include<bits/stdc++.h>
#define Rep(i,a,b) for(register int i=(a);i<=(b);++i)
#define Repe(i,a,b) for(register int i=(a);i>=(b);--i)
#define pb push_back
#define mp make_pair
#define Chkmax(a,b) a=a>b?a:b
#define Chkmin(a,b) a=a<b?a:b
#define mx(a,b) (a>b?a:b)
#define mn(a,b) (a<b?a:b)
typedef unsigned long long uint64;
typedef unsigned int uint32;
typedef long long ll;
using namespace std;

namespace IO
{
    const uint32 Buffsize=1<<15,Output=1<<23;
    static char Ch[Buffsize],*S=Ch,*T=Ch;
    inline char getc()
	{
		return((S==T)&&(T=(S=Ch)+fread(Ch,1,Buffsize,stdin),S==T)?0:*S++);
	}
    static char Out[Output],*nowps=Out;

    inline void flush(){fwrite(Out,1,nowps-Out,stdout);nowps=Out;}

    template<typename T>inline void read(T&x)
	{
		x=0;static char ch;T f=1;
		for(ch=getc();!isdigit(ch);ch=getc())if(ch=='-')f=-1;
		for(;isdigit(ch);ch=getc())x=x*10+(ch^48);
		x*=f;
	}

	template<typename T>inline void write(T x,char ch='\n')
	{
		if(!x)*nowps++='0';
		if(x<0)*nowps++='-',x=-x;
		static uint32 sta[111],tp;
		for(tp=0;x;x/=10)sta[++tp]=x%10;
		for(;tp;*nowps++=sta[tp--]^48);
		*nowps++=ch;
	}
}
using namespace IO;

inline void file()
{
#ifndef ONLINE_JUDGE
	FILE*LI=freopen("life.in","r",stdin);
	FILE*FE=freopen("life.out","w",stdout);
#endif
}

const int MAXN=2011;

static int n,x,y;

static long double sx,sy;

static struct node
{
	double x,y;
	friend bool operator<(node a,node b)
	{return fabs(a.x-b.x)>1e-8?a.x<b.x:a.y<b.y;}

	friend bool operator==(node a,node b)
	{return fabs(a.x-b.x)+fabs(a.y-b.y)<1e-8;}
}p[MAXN],q[MAXN*MAXN];

inline void init()
{
	read(n);sx=sy=0;
	Rep(i,1,n)read(p[i].x),read(p[i].y),sx+=p[i].x,sy+=p[i].y;
}

static int tt;

static int nf;

static double shad[MAXN];

inline double getshadow(double x,double y,double u,double v)
{return (x*v-y*u>0?-1:1)*sqrt(x*x+y*y-(x*u+y*v)*(x*u+y*v)/(u*u+v*v));}

inline int Chk(double x,double y)
{
	Rep(i,1,n)shad[i]=getshadow(p[i].x,p[i].y,x,y);
	sort(shad+1,shad+n+1);
	//cout<<x<<' '<<y<<endl;
	//Rep(i,1,n)cout<<shad[i]<<' ';cout<<endl;
	double md=getshadow(sx,sy,x,y);
	//cout<<md<<endl;
	Rep(i,1,n/2)if(fabs(2*md-shad[i]-shad[n-i+1])>1e-8)return 0;
	return 1;
}

inline void solve()
{
	sx/=n,sy/=n;
	sort(p+1,p+n+1),n=unique(p+1,p+n+1)-p-1;
	Rep(i,1,n)q[i].x=2*sx-p[i].x,q[i].y=2*sy-p[i].y;
	tt=0;
	Rep(i,1,n)
	{
		int flg=1;
		Rep(j,1,n)if(fabs(p[i].x-q[j].x)+fabs(p[i].y-q[j].y)<=1e-8)
		{flg=0;break;}
		if(flg)p[++tt]=p[i];
	}
	n=tt,tt=0;
	//Rep(i,1,n)cout<<p[i].x<<' '<<p[i].y<<endl;
	if(n<=2)puts("-1"),exit(0);
	Rep(i,1,n-1)Rep(j,i+1,n)
	{
		double x=2*sx-p[j].x-p[i].x,y=2*sy-p[j].y-p[i].y;
		if(fabs(x)>0)y/=x,x=1;
		else x=0,y=1;
		q[++tt]=(node){x,y};
	}
	//cerr<<n<<endl;
	sort(q+1,q+tt+1);
	int fp=1;
	int ans=0;
	Rep(i,1,tt+1)
	{
		if(fabs(q[i].x-q[fp].x)+fabs(q[i].y-q[fp].y)<=1e-8)continue;
		if(i-fp<n/2){fp=i;continue;}
		if(Chk(q[fp].x,q[fp].y))++ans;
		fp=i;
	}
	cout<<ans<<endl;
}

int main()
{
    //static int _;
    //read(_);
    //while(_--)
    init();
    solve();
    return 0;
}

/*
	Eduardo Quintana Miranda
	Geometry for contests
	2015

	update:
	14-11-2017

	todo:

	suggested problems:
*/

// ------------------begin-Geometry---------------------

#include <utility>
#include <iostream>
#include <cmath>
#include <cassert>
#include <algorithm>
#include <vector>
//#include <initializer_list>
//#define poly_N 55
//#define DEBUG(x) cout << #x << " = " << x << endl
using namespace std;

const double 	EPS=1e-8,
				PI=acos(-1.0);

int sign(double a){
	if(fabs(a)<EPS) return 0;
	return a<0 ? -1 : 1;
}

template<class T> T mod(T a, T b){return a - b*floor(a/b);}
template<class T> T sqr(T a){return a*a;}
template<class T> T minus(T a){return -a;}

//--------------POINT-----------------------
	class point{
		private:
			friend ostream& operator<<(ostream&,const point&);
			friend istream& operator>>(istream&,point&);

		protected:

		public:
			vector<double> x;

			int size()const{return x.size();}
			point();
			point(unsigned int);
			//point(initializer_list<double>);
			point(const vector<double>&);
			point(const point&); //cpy ctor
			point(point&&); //move ctor

			bool operator < (const point&) const;
			bool operator==(const point&)const;

			double operator%(const point& )const;
			double operator*(const point&)const;
			double& operator[](unsigned int);
			double operator[](unsigned int)const;

			point& operator = (point&&) ; //move assign
			point& operator = (const point& ); //cpy assign

			point& operator+=(const point& );
			point operator+(const point& )const;
			point& operator-=(const point& );
			point operator-(const point& )const;

			point& operator*=(const double& );
			point operator*(const double& )const;
			friend point operator*(const double&,const point&);

			point& operator/=(const double& );
			point operator/(const double& )const;
			point operator^(const point& )const;

			void resize(unsigned int);

			//friend point operator*(point,double);
			friend double abs(point);
			friend double abs2(point);

	};

	ostream& operator<<(ostream& os,const point& P){
		//os<<"( ";
		for(auto& i: P.x){
			if(&i != &P.x.front()) os<<" ";
			os<< i;
		}
		//os<<" )";
		return os;
	}
	istream& operator>>(istream& is,point& P){
		for_each(P.x.begin(),P.x.end(),
			[&](double& v){is>>v;}
		);
		return is;
	}
	point::point(){}
	point::point(unsigned int DIM): x(DIM,0){}
	point::point(const vector<double>& V): x(V){}
	point::point(const point &P): x(P.x){}
	point::point(point &&P){
		x=move(P.x);
	}

	void point::resize(unsigned int dim){
		x.resize(dim);
	}
	bool point::operator < (const point& P) const{
		assert(P.size()==size());
		for(int i=0;i<size();i++)if(fabs(x[i]-P.x[i])>EPS) return x[i] < P.x[i];
		return false;
	}
	double& point::operator[](unsigned int i){
		assert(i<size());
		return x[i];
	}
	double point::operator[](unsigned int i)const{
		assert(i<size());
		return x[i];
	}
	point& point::operator = (point&& that){
		x=move(that.x);
		return *this;
	}
	point& point::operator = (const point& that){
		x=that.x;
		return *this;
	}
	point& point::operator+=(const point& that){
		assert(size()==that.size());
		for(int i=0;i<size();i++){
			x[i]+=that.x[i];
			//if(sign(x[i])==0)x[i]=0;//round-off correction
		}
		return *this;
	}
	point point::operator+(const point& that)const{
		return point(*this)+=that;
	}
	point& point::operator-=(const point& that){
		assert(size()==that.size());
		for(int i=0;i<size();i++){
			x[i]-=that.x[i];
			//if(sign(x[i])==0)x[i]=0;//round-off correction
		}
		return *this;
	}
	point point::operator-(const point& that)const{
		return point(*this)-=that;
	}
	point& point::operator*=(const double& v){
		for(auto& i: x)i*=v;
		return *this;
	}
	point point::operator*(const double& v)const{
		return point(*this)*=v;
	}
	point operator*(const double& v,const point& P){
		return point(P)*=v;
	}
	point& point::operator/=(const double& v){
		for(auto& i: x)i/=v;
		return *this;
	}
	point point::operator/(const double& v)const{
		return point(*this)/=v;
	}
	double point::operator*(const point& that)const {
		assert(size()==that.size());
		double s=0;
		for(int i=0;i<size();i++)s+= x[i]*that.x[i];
		return s;
	}
	bool point::operator==(const point& that)const{
		return abs(*this-that)<EPS;
	}
	point point::operator^(const point& P)const{
		assert(P.size()==size() && size()==3);
		return point({
			x[1]*P[2]-x[2]*P[1],
			x[2]*P[0]-x[0]*P[2],
			x[0]*P[1]-x[1]*P[0]});
	}
	double point::operator%(const point& P)const{
		assert(size()==P.size() && (size()==3 || size()==2));
		if(size()==2)
			return x[0]*P[1]-x[1]*P[0];
		return abs(*this ^ P);
	}

	double abs(point p){
		return sqrt(fabs(p*p));
	}
	double abs2(point p){
		return fabs(p*p);
	}
	double angle(point A,point B){
		/*angle A to B*/
		return atan2(A%B,A*B);
	}
	point normalize(point P){ //returns a unique vector parallel to P with norm 1.
		double m=abs(P);
		if(fabs(m)<EPS){
			P=point(P.size());
			//cout<<"here 1\n";
		}else{
			//cout<<"here 2\n";
			P *= 1./m;
			for(int i=0;i<P.size();i++)
				if(sign(P[i])!=0){
					P *= sign(P[i]);
					break;
				}
		}
		return P;
	}

#include <iostream>
#include <set>
#include <map>
using namespace std;

typedef long long ll;

const point zero(2);
point V[2010];
int N;

bool good(point &L){
	map<ll,int> S;
	for(int i=0;i<N;i++){
		ll b,a=L * V[i] ;
		b=a*(-1.);

		if(S[b]>0){
			S[b]--;
		}else{
			S[a]++;
		}

	}
	S[0]=0;
	int s=0;
	for(auto p: S)	s+=p.second;
	return s==0;
}

int main(){
	point com(zero);

	cin>>N;
	for(int i=0;i<N;i++){
		V[i]=zero;
		cin>>V[i];
		com+=V[i];
	}
	com/=N;

	//move to Center of Mass
	for(int i=0;i<N;i++)V[i]-=com;

	//Remove symmetric points

	for(int i=0;i<N;){
		bool ok=true;
		for(int j=i;j<N;j++)
		if((V[i]+V[j])==zero){
			ok=false;
			if(i!=j){
				V[j]=V[--N];
			}
			V[i]=V[--N];
		}
		if(ok)break;
	}

	//if(N==2000)return 0;
	//Remove points at COM
	for(int i=0;i<N;i++)
		if(V[i]==zero)V[i]=V[--N];

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

	//cout<<"POINTS:\n";
	//for(auto p: V)cout<<p*4.<<endl;

	//return 0;

	set<point> ct;

	for(int i=0;i<N;i++){
		point d=V[i]+V[0];
		d=point({d[1],0-d[0]});
		if( good(d) )ct.insert(normalize(d));
	}

	cout<<ct.size()<<endl;

	return 0;
}

#include<cstdio>
#include<utility>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps=1e-9;
const int N=2000;
struct yuurei
{
	double x,y;
	yuurei(double x_,double y_):x(x_),y(y_){}
	yuurei(){x=0,y=0; }
	yuurei operator +(yuurei a)
	{
		return yuurei(x+a.x,y+a.y);
	}
	yuurei operator -(yuurei a)
	{
		return yuurei(x-a.x,y-a.y);
	}
	double operator *(yuurei a)
	{
		return x*a.x+y*a.y;
	}
	yuurei operator /(double a)
	{
		return yuurei(x/a,y/a);
	}
	bool operator ==(yuurei a)
	{
		return fabs(x-a.x)<eps&&fabs(y-a.y)<eps;
	}
}p[N+10],G,mid,vec;
int T,n,x,ans,id[N+10];
pair<double,int>a[N+10];
bool check(int pos)
{
	mid=(p[x]+p[pos])/2;
	vec=G-mid;
	vec=yuurei(vec.y,-vec.x);
	for(int i=1;i<=n;i++) a[i]=make_pair(vec*p[i],i);
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++) id[a[i].second]=i;
	if(id[x]+id[pos]!=n+1) return 0;
	double cmp=a[1].first+a[n].first;
	for(int i=1;i<=n;i++)
		if(fabs(a[i].first+a[n-i+1].first-cmp)>eps) return 0;
	return 1;
}
int main()
{
	scanf("%d",&n);
	G=yuurei(0,0);
	for(int i=1;i<=n;i++)
	{
		double a,b;
		scanf("%lf%lf",&a,&b);
		p[i]=yuurei(a,b);
		G=G+p[i];
	}
	G=G/n;
	x=ans=0;
	for(int i=1;i<=n;i++)
	{
		bool flag=0;
		for(int j=1;j<=n;j++)
			if(p[i]+p[j]==G+G) flag=1;
		if(!flag) x=i;
	}
	if(!x){printf("-1\n"); return 0;}
	for(int i=1;i<=n;i++)
		if(check(i)) ans++;
	printf("%d\n",ans);
	return 0;
}

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

template <typename T>
ostream& operator <<(ostream& out, const vector<T>& vec) {
    out << "[";
    for (int x : vec) out << x << ", ";
    out << "]";
    return out;
}

#if DEBUG && !ONLINE_JUDGE
    ifstream input_from_file("input.txt");
    #define cin input_from_file
    #define dbg_var(x) clog << #x << ": " << x << endl;
#endif

short int GetSign(LL val){ return (val > 0) - (val < 0); }

struct point{
    LL x, y;
    point(): x(0), y(0) {}
    point(LL x, LL y): x(x), y(y) {}
    bool operator == (const point &other) const{return x == other.x and y == other.y;}
    bool operator < (const point &other) const{if(x == other.x) return y < other.y; return x < other.x;}
    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 * (LL l) const{return point(x*l, y*l);}
    LL operator *(const point &other) const{return x*other.x + y*other.y;}
    LL operator ^ (const point &other){return x*other.y - y*other.x;}
    point Rotate90(){return point(-y, x);}
};

short int RelativePosition(const point& O, const point& A, const point& B){
    return GetSign((A-O)^(B-O));
}

vector<int> ConvexHull(const vector<point>& points) {
    int N = points.size();
    vector <int> sorted_indexes(N);
    for (int i = 0; i < (int)sorted_indexes.size(); i++) sorted_indexes[i] = i;

	// Sorting from south to north (and from west to east) the points.
    sort(sorted_indexes.begin(), sorted_indexes.end(),
        [&points](int i, int j) {
            return points[i] < points[j];
        });

    vector<int> anticlockwise, clockwise;
    anticlockwise.push_back(sorted_indexes[0]);
    clockwise.push_back(sorted_indexes[0]);

	for (int i = 1; i < N; i++) {
        // Finds the convex hull of the first i+1 points.
        int index = sorted_indexes[i];
		point V = points[index];

        // Comparing V with the line generated by the last two points in
        // the anticlockwise array.
		while (anticlockwise.size() > 1 and
               RelativePosition(points[anticlockwise.rbegin()[1]], V,
                                points[anticlockwise.back()]) != -1) {
            anticlockwise.pop_back();
        }
		anticlockwise.push_back(index);

        // Comparing V with the line generated by the last two points in
        // the clockwise array.
        while (clockwise.size() > 1 and
               RelativePosition(points[clockwise.rbegin()[1]], V,
                                points[clockwise.back()]) != 1) {
            clockwise.pop_back();
        }
		clockwise.push_back(index);
	}

    // Joining anticlockwise and clockwise in a single vector.
    anticlockwise.pop_back();
    reverse(clockwise.begin(), clockwise.end());
    clockwise.pop_back();
    anticlockwise.insert(anticlockwise.end(), clockwise.begin(), clockwise.end());
    return anticlockwise;
}

inline short int VectorsRelativePosition(point A, point B, point U, point V) {
    return RelativePosition(point(), U-V, A-B);
}

vector<pair<int, int>> RotatingCalipers(const vector<point> points) {
    const vector<int>& ch = ConvexHull(points);

    if (ch.size() == 1) return {make_pair(ch[0], ch[0])};
    if (ch.size() == 2) return {make_pair(ch[0], ch[1])};

    vector<pair<int,int>> res;
    int N = ch.size();

    // The indexes i and it should be such that ch[i] and ch[it] form
    // an antipodal pair.
    int it = 1;
    for (int i = 0; i < N; i++) {
        // Q is the current point, P and Q are respectively the point before
        // and after the current one.
        point P = points[ch[(i+(N-1)) % N]];
        point Q = points[ch[i]];
        point R = points[ch[(i+1) % N]];

        // X is the point identified by it, Y is the following one.
        point X = points[ch[it]];
        point Y = points[ch[(it+1) % N]];

        // it is increased as much as needed to form an antipodal pair with
        // i.
        while (VectorsRelativePosition(Q, P, Y, X) < 0) {
            it = (it+1)%N;
            X = points[ch[it]];
            Y = points[ch[(it+1) % N]];
        }
        // All possible values for it are iterated until it does not form an
        // antipodal pair anymore.
        while (VectorsRelativePosition(R, Q, Y, X) <= 0) {
            res.push_back(make_pair(ch[i], ch[it]));
            it = (it+1)%N;
            X = points[ch[it]];
            Y = points[ch[(it+1) % N]];
        }
    }

    return res;
}

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

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

    point center_of_mass;
    for(int i=0; i<n; i++) center_of_mass = center_of_mass + p[i];

    vector<bool> always_symmetric(n, false);
    for(int i=0; i<n; i++)
        for(int j=i; (not always_symmetric[i]) and j<n; j++) if(not always_symmetric[j]){
            if(center_of_mass*2 == (p[i]+p[j])*n){
                always_symmetric[i] = always_symmetric[j] = true;
            }
        }

    vector<point> new_p;
    for(int i=0; i<n; i++) if(not always_symmetric[i]) new_p.push_back(p[i]);
    p = new_p;
    n = p.size();

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

    center_of_mass = {0,0};
    for(int i=0; i<n; i++) center_of_mass = center_of_mass + p[i];

    vector<pair<int,int>> rc = RotatingCalipers(p);
    vector<point> ans;
    for(auto x:rc){
        point M = p[x.first] + p[x.second];
        point V = (center_of_mass*2 - M*n).Rotate90();
        vector<LL> proj;
        for(point &P:p) proj.push_back(P*V);
        sort(proj.begin(), proj.end());
        LL projM = M*V;
        vector<LL> rproj = proj;
        reverse(rproj.begin(), rproj.end());
        bool ok = true;
        for(int i=0; i<n; i++) if(proj[i] + rproj[i] != projM) ok = false;
        if(ok) ans.push_back(V);
    }

    for(auto &P:ans){
        LL g = __gcd(P.x, P.y);
        P.x /= g;
        P.y /= g;
        if(P.y < 0) {P.y = -P.y; P.x = -P.x;}
        else if(P.y == 0) if(P.x < 0) {P.y = -P.y; P.x = -P.x;}
    }
    sort(ans.begin(), ans.end());
    auto it = unique(ans.begin(), ans.end());
    cout << it-ans.begin() << '\n';
}

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
#define fo(i,a,b) for(int i=(a);i<=(b);++i)
#define fd(i,a,b) for(int i=(a);i>=(b);--i)
#define mset(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef double db;
typedef long long ll;
const int N=2005;
int read()
{
	char ch;int n=0,p=1;
	for(ch=getchar();ch<'0' || '9'<ch;ch=getchar())if(ch=='-') p=-1;
	for(;'0'<=ch && ch<='9';ch=getchar())n=n*10+ch-'0';
	return n*p;
}
struct dot
{
	db x,y;
	friend dot operator + (dot a,dot b){return (dot){a.x+b.x,a.y+b.y};}
	friend dot operator - (dot a,dot b){return (dot){a.x-b.x,a.y-b.y};}
	friend dot operator * (db k,dot a){return (dot){k*a.x,k*a.y};}
	friend db operator ^ (dot a,dot b){return a.x*b.y-a.y*b.x;}
	friend bool operator == (dot a,dot b){return a.x==b.x && a.y==b.y;}
}a[N],b[N],G;
int n,m,ans;
bool bz[N];
db d[N];
map<ll,int> cnt;
int main()
{
		G=(dot){0,0};
		n=read();
		fo(i,1,n) a[i].x=read(),a[i].y=read(),G=G+a[i];
		G=(1.0/n)*G;
		mset(bz,0);
		fo(i,1,n-1)
			fo(j,i+1,n) if(abs(a[i].x+a[j].x-2*G.x)<=1e-7 && abs(a[i].y+a[j].y-2*G.y)<=1e-7) bz[i]=bz[j]=1;
		m=0;
		fo(i,1,n) if(!bz[i]) b[++m]=a[i];
		if(m<=2) return puts("-1"),0;
		cnt.clear();
		int ans=0;
		fo(i,1,m-1)
			fo(j,i+1,m)
			{
				dot p=0.5*(b[i]+b[j]);
				db angle = (p.x < G.x || (p.x == G.x && p.y < G.y)) ? atan2(G.y - p.y, G.x - p.x)
																    : atan2(p.y - G.y, p.x - G.x);
				ll val=(ll)((angle*1e7)+0.5);
				if(cnt[val]==-1) continue;
				if(++cnt[val]>=m/2)
				{
					fo(k,1,m) d[k]=(p-G)^(b[k]-G);
					sort(d+1,d+m+1);
					bool ok=1;
					fo(i,1,m/2) if(abs(d[i]+d[m-i+1])>1e-7) {ok=0;break;}
					ans+=ok;
					cnt[val]=-1;
				}
			}
		printf("%d\n",ans);
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<long double, long double> pii;

#define mp make_pair
#define pb push_back
#define double long double

int n;
pii a[2000];
const double eps = 1e-7;
char out[2000];
vector<pii> b;
set<pii> u;

double dist(double x1, double y1, double x2, double y2){
    return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

inline double det(double a, double b, double c, double d){
    return a * d - b * c;
}

bool operator < (const pii &lhs, const pii &rhs){
    return (lhs.first + eps < rhs.first) || (abs(lhs.first - rhs.first) < eps && (lhs.second + eps < rhs.second));
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n;
    for(int i = 0; i < n; i++) cin >> a[i].first >> a[i].second;
    double x0 = 0, y0 = 0;
    for(int i = 0; i < n; i++){
        x0 += a[i].first;
        y0 += a[i].second;
    }
    x0 /= n;
    y0 /= n;
    for(int i = 0; i < n; i++){
        if(out[i]) continue;
        for(int j = i + 1; j < n; j++){
            double x1 = a[i].first, y1 = a[i].second;
            double x2 = a[j].first, y2 = a[j].second;
            double a = y2 - y1;
            double b = x1 - x2;
            double c = x2 * y1 - x1 * y2;
            double d1 = dist(x1, y1, x0, y0);
            double d2 = dist(x2, y2, x0, y0);
            double val = a * x0 + b * y0 + c;
            if(abs(d1 - d2) < eps && abs(val) < eps){
                out[i] = true;
                out[j] = true;
                break;
            }
        }
    }
    int cnt = 0;
    for(int i = 0; i < n; i++){
        if(!out[i]){
            cnt++;
            b.pb(a[i]);
        }
    }
    if(cnt == 0 || (n == 1)) cout << -1 << endl;
    else{
        b.pb(mp(x0, y0));
        int m = b.size();
        double x1 = b.front().first, y1 = b.front().second;
        int ans = 0;
        for(int i = 1; i < m; i++){
            double x2 = b[i].first, y2 = b[i].second;
            double x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2;
            double px = y0 - y3, py = x3 - x0;
            if(abs(px) < eps && abs(py) < eps) continue;
            bool c = false;
            for(auto v: u){
                if(abs(px * v.second - py * v.first) < eps){
                    c = true;
                    break;
                }
            }
            u.insert(mp(px, py));
            if(c) continue;
            double na = py, nb = -px, nc = 0;
            bool ok = true;
            vector<pii> d;
            double x00, y00;
            for(int j = 0; j < m; j++){
                double ma = nb, mb = -na, mc = -nb * b[j].first + na * b[j].second;
                double z = det(na, nb, ma, mb);
                double x = -det(nc, nb, mc, mb) / z;
                double y = -det(na, nc, ma, mc) / z;
                if(j < m - 1) d.pb(mp(x, y));
                else x00 = x, y00 = y;
            }
            sort(d.begin(), d.end());
            int k = d.size();
            for(int j = 0; j < (int)d.size() / 2; j++){
                double x1 = d[j].first, y1 = d[j].second;
                double x2 = d[k - 1 - j].first, y2 = d[k - 1 - j].second;
                if(!(abs((x1 + x2) / 2 - x00) < eps && abs((y1 + y2) / 2 - y00) < eps)){
                    ok = false;
                    break;
                }
            }
            ans += ok;
        }
        cout << ans << endl;
    }
    return 0;
}

#include <bits/stdc++.h>

typedef long long ll;
const int N = 5005;

int n;
ll f[N];
bool vis[N];
std::map<std::pair<int, int>, bool> map;
inline ll gcd(ll x, ll y)
{
	return y ? gcd(y, x % y) : x;
}

inline bool work()
{
	int l = 1, r = n;
	while (l <= r && f[l] + f[r] == 0) ++l, --r;
	return l > r;
}

struct Point
{
	ll x, y;
	Point (ll x = 0, ll y = 0) : x(x), y(y){}
} P[N], Q[N], G;

inline Point operator+(const Point &u, const Point &v) { return Point(u.x + v.x, u.y + v.y); }
inline Point operator-(const Point &u, const Point &v) { return Point(u.x - v.x, u.y - v.y); }
inline Point operator*(const ll k, const Point &v) { return Point(k * v.x, k * v.y); }
inline bool operator==(const Point &a, const Point &b) { return a.x == b.x && a.y == b.y; }

inline bool ref(Point A, Point B, Point M)
{
	return 2 * M == A + B;
}

inline char nc()
{
	static char buf[1000000], *p1 = buf,*p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}

inline ll read()
{
	ll res = 0, neg = 1;
	char ch;
	do
	{
		ch = nc();
		if (ch == '-') neg = -1;
	} while (ch < 48 || ch > 57);
	do res = res * 10 + ch - 48, ch = nc(); while (ch >= 48 && ch <= 57);
	return res * neg;
}

int main(int, char**)
{
	n = read();
	for (int i = 1; i <= n; ++i)
	{
		P[i].x = read() * n, P[i].y = read() * n;
		G = G + P[i];
	}
	G.x /= n, G.y /= n;
	for (int i = 1; i <= n; ++i) P[i] = P[i] - G;
	Point O(0, 0);
	for (int i = 1; i <= n; ++i)
	{
		if (P[i] == Point(0, 0)) vis[i] = true;
		else
		{
			for (int j = 1; j < i; ++j)
			{
				if (P[i] + P[j] == O)
				{
					vis[i] = vis[j] = true;
					break;
				}
			}
		}
	}
	int m = n;
	n = 0;
	for (int i = 1; i <= m; ++i) if (!vis[i]) Q[++n] = P[i];
	if (n <= 2) return printf("-1"), 0;
	int ans = 0;
	for (int i = 1; i <= n; ++i)
	{
		Point R = Q[1] + Q[i];
		ll x = R.x, y = R.y, g = gcd(x, y);
		x /= g, y /= g;

		if (!map.count(std::make_pair(x, y)))
		{
			for (int j = 1; j <= n; ++j) f[j] = x * Q[j].y - Q[j].x * y;
			std::sort(f + 1, f + n + 1);
			if (work())
			{
				++ans;
				map[std::make_pair(x, y)] = true;
			}
		}
	}
	printf("%d", ans);
	return 0;
}

#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <list>
#include <cassert>
#include <ctime>
#include <climits>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)
#define REPE(i,n) FORE(i,0,n)
#define FORSZ(i,a,v) FOR(i,a,SZ(v))
#define REPSZ(i,v) REP(i,SZ(v))
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); }

const int MAXN=2000;
typedef struct P { ll x,y; P() {} P(ll x,ll y):x(x),y(y) {} } P;
bool operator<(const P &a,const P &b) { if(a.x!=b.x) return a.x<b.x; return a.y<b.y; }
bool operator==(const P &a,const P &b) { return a.x==b.x&&a.y==b.y; }
P operator-(const P &a,const P &b) { return P(a.x-b.x,a.y-b.y); }
ll operator*(const P &a,const P &b) { return a.x*b.x+a.y*b.y; }

int n;
P p[MAXN];
P c; int mlt;

ll v[MAXN];

bool ok(const P &dir) {
	//printf("testing (%lld,%lld)\n",dir.x,dir.y);
	REP(i,n) v[i]=p[i]*dir; sort(v,v+n);
	//printf("v:"); REP(i,n) printf(" %lld",v[i]); puts("");
	ll sum=v[0]+v[n-1]; REP(i,n) if(v[i]+v[n-i-1]!=sum) return false;
	return true;
}

void run() {
	scanf("%d",&n); REP(i,n) scanf("%lld%lld",&p[i].x,&p[i].y);

	mlt=n; c.x=c.y=0; REP(i,n) c.x+=p[i].x,c.y+=p[i].y;

	set<P> have;
	REP(i,n) {
		P cur=P(mlt*p[i].x,mlt*p[i].y);
		P opp=c-(cur-c);
		if(cur==opp) continue; else if(have.count(opp)) have.erase(opp); else have.insert(cur);
	}
	n=0; for(auto it=have.begin();it!=have.end();++it) p[n++]=P(it->x/mlt,it->y/mlt);
	if(n==0) { printf("-1\n"); return; }
	//printf("prem:"); REP(i,n) printf(" (%lld,%lld)",p[i].x,p[i].y); printf(" c=(%lld,%lld) mlt=%d\n",c.x,c.y,mlt);

	set<P> ptest;
	REP(j,n) {
		P a=P(2*c.x,2*c.y),b=P(mlt*(p[0].x+p[j].x),mlt*(p[0].y+p[j].y));
		P dir=P((b-a).y,-(b-a).x); if(dir.x<0||dir.x==0&&dir.y<0) dir.x=-dir.x,dir.y=-dir.y; ll g=gcd(dir.x,abs(dir.y)); dir.x/=g,dir.y/=g;
		ptest.insert(dir);
		//printf("test dir=(%lld,%lld)\n",dir.x,dir.y);
	}

	int ret=0;
	for(auto it=ptest.begin();it!=ptest.end();++it) if(ok(*it)) ++ret;
	printf("%d\n",ret);
}

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

#include<bits/stdc++.h>
using namespace std;
int n,id[2005],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};
	}
	P operator /(double a){
		return (P){x/a,y/a};
	}
	double operator *(P a){
		return x*a.x+y*a.y;
	}
	bool operator ==(P a){
		return fabs(x-a.x)<1e-9&&fabs(y-a.y)<1e-9;
	}
}p[2005],rt,mid,vec;
pair<double,int> a[2005];
bool check(int pos){
	mid=(p[x]+p[pos])/2;
	vec=rt-mid;
	vec=(P){vec.y,-vec.x};
	for (int i=1;i<=n;i++)
		a[i]=make_pair(vec*p[i],i);
	sort(a+1,a+n+1);
	for (int i=1;i<=n;i++)
		id[a[i].second]=i;
	if (id[x]+id[pos]!=n+1) return 0;
	double flag=a[1].first+a[n].first;
	for (int i=1;i<=n;i++)
		if (abs(a[i].first+a[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);
		rt=rt+p[i];
	}
	rt=rt/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]==rt+rt) is=1;
		if (!is) inf=0,x=i;
	}
	if (inf)
		return puts("-1"),0;
	int ans=0;
	for (int i=1;i<=n;i++)
		if (check(i)) ans++;
	printf("%d",ans);
}

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

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
const int N=2e3+2;
const double eps=1e-6,inf=1e7;
struct str
{
	double x,y;
};
double ly,dis[N];
str p[N],pp[N],line[N*N],av[N*N],mid,m;
bool ed[N];
int n,i,j,t,c,cc,ls,x,y,z,ds,as,ans,fh;
inline int read()
{
	c=getchar();fh=1;
	while ((c<48)||(c>57))
	{
		if (c=='-') fh=-1;
		c=getchar();
	}
	cc=c^48;c=getchar();
	while ((c>=48)&&(c<=57))
	{
		cc=cc*10+(c^48);
		c=getchar();
	}
	return cc*fh;
}
inline double jdz(double x)
{
	return (x>0) ? x:-x;
}
void qs(int l,int r)
{
	int i=l,j=r;
	double mx=line[l+r>>1].x,my=line[l+r>>1].y;
	while (i<=j)
	{
		while (line[i].y*mx>line[i].x*my) ++i;
		while (line[j].y*mx<line[j].x*my) --j;
		if (i<=j) swap(line[i++],line[j--]);
	}
	if (i<r) qs(i,r);
	if (l<j) qs(l,j);
}
inline double dist(int a,str b)
{
	return (av[a].x*b.x-av[a].y*b.y)*(av[a].x*b.x-av[a].y*b.y)/(av[a].x*av[a].x+av[a].y*av[a].y);
}
int main()
{
	//freopen("life.in","r",stdin);
	//freopen("life.out","w",stdout);
	//t=read();
	//while (t--)
	//{
		m.x=m.y=0;
		memset(ed,false,sizeof(ed));ds=0;ls=0;as=0;
		ans=0;
		n=read();
		for (i=1;i<=n;i++)
		{
			p[i].x=read();p[i].y=read();
			m.x+=p[i].x;m.y+=p[i].y;
		}
		m.x/=n;m.y/=n;
		for (i=1;i<=n;i++) for (j=i+1;j<=n;j++) if ((jdz((p[j].y-p[i].y)*(p[j].x-m.x)-(p[j].y-m.y)*(p[j].x-p[i].x))<eps)&&(jdz(p[j].x+p[i].x-m.x*2)<eps)&&(jdz(p[j].y+p[i].y-m.y*2)<eps)) ed[i]=ed[j]=1;
		for (i=1;i<=n;i++) if (!ed[i]) pp[++ds]=p[i];
		n=ds;
		if (n<=2)
		{
			printf("-1\n");
			return 0;//continue;
		}
		for (i=1;i<=n;i++) p[i]=pp[i];
		for (i=1;i<=n;i++) for (j=i+1;j<=n;j++)
		{
			mid.x=(p[i].x+p[j].x)/2;
			mid.y=(p[i].y+p[j].y)/2;
			line[++ls].x=m.x-mid.x;
			line[ls].y=mid.y-m.y;
			if (line[ls].y<-eps)
			{
				line[ls].x=-line[ls].x;
				line[ls].y=-line[ls].y;
			}
			if (jdz(line[ls].y)<eps)
			{
				line[ls].x=1;
			}
		}
		qs(1,ls);
		for (i=1;i+(n>>1)-1<=ls;i+=j)
		{
			for (j=1;j<n>>1;j++) if ((jdz(line[i].x*line[j+i].y-line[i].y*line[j+i].x)>eps)) break;
			if (j==n>>1) av[++as]=line[i];
			while ((i+j<=ls)&&(jdz(line[i].x*line[j+i].y-line[i].y*line[j+i].x)<eps)) ++j;
		}
		for (i=1;i<=as;i++)
		{
			for (j=1;j<=n;j++)
			{
				dis[j]=sqrt(p[j].x*p[j].x+p[j].y*p[j].y-dist(i,p[j]));
				if (av[i].x*p[j].y+av[i].y*p[j].x>eps) dis[j]=-dis[j];
			}
			sort(dis+1,dis+n+1);
			ly=dis[1]+dis[n];
			++ans;
			for (j=2;j<=n+1>>1;j++) if (jdz((dis[j]+dis[n+1-j])-ly)>eps)
			{
				--ans;
				break;
			}
		}
		printf("%d\n",ans);
	//}
}

#include<bits/stdc++.h>
using namespace std;
#define REP(i,st,ed) for(register int i=st,i##end=ed;i<=i##end;++i)
#define DREP(i,st,ed) for(register int i=st,i##end=ed;i>=i##end;--i)
typedef long long ll;
template<typename T>inline bool chkmin(T &x,T y){return (y<x)?(x=y,1):0;}
template<typename T>inline bool chkmax(T &x,T y){return (y>x)?(x=y,1):0;}
inline int read(){
	int x;
	char c;
	int f=1;
	while((c=getchar())!='-' && (c>'9' || c<'0'));
	if(c=='-') f=-1,c=getchar();
	x=c^'0';
	while((c=getchar())>='0' && c<='9') x=(x<<1)+(x<<3)+(c^'0');
	return x*f;
}
inline ll readll(){
	ll x;
	char c;
	int f=1;
	while((c=getchar())!='-' && (c>'9' || c<'0'));
	if(c=='-') f=-1,c=getchar();
	x=c^'0';
	while((c=getchar())>='0' && c<='9') x=(x<<1ll)+(x<<3ll)+(c^'0');
	return x*f;
}
const int maxn=2000+10;
const long double eps=(1e-9);
struct point{
	long double x,y;
	point operator +(const point &rhs) const{
		return (point){x+rhs.x,y+rhs.y};
	}
	point operator -(const point &rhs) const{
		return (point){x-rhs.x,y-rhs.y};
	}
	point operator /(const int &rhs) const{
		return (point){x/rhs,y/rhs};
	}
	bool operator ==(const point &rhs) const{
		return fabs(x-rhs.x)<=eps && fabs(y-rhs.y)<=eps;
	}
	long double operator *(const point &rhs) const{
		return x*rhs.x+y*rhs.y;
	}
	void clear(){
		x=y=0;
	}
}a[maxn],rt,ve;
long double p[maxn];
int n,ans,st,id[maxn];
bool cmp(const int A,const int B){
	return p[A]<p[B] || (p[A]==p[B] && A<B);
}
inline void get_ans(int x){
	ve=(a[x]+a[st])/2;
	ve=rt-ve;
	ve=(point){ve.y,-ve.x};
	REP(i,1,n) id[i]=i,p[i]=ve*a[i];
	sort(id+1,id+n+1,cmp);
	long double num=p[id[1]]+p[id[n]];
	int u=0;
	REP(i,1,n/2+1) if(fabs(num-p[id[i]]-p[id[n+1-i]])>eps) return;
	REP(i,1,n){
		if(id[i]==x) u+=i;
		if(id[i]==st) u+=i;
	}
	if(u!=n+1) return;
	++ans;
}
inline void work(){
	ans=0;
	rt.clear();
	n=read();
	REP(i,1,n) a[i].x=read(),a[i].y=read(),rt=rt+a[i];
	rt=rt/n;
	st=0;
	REP(i,1,n){
		bool flag=1;
		REP(j,1,n) if((a[i]+a[j])/2==rt){
			flag=0;
			break;
		}
		if(flag) st=i;
	}
	if(!st){
		printf("-1\n");
		return;
	}
	REP(i,1,n) get_ans(i);
	printf("%d\n",ans);
}
int main(){
	work();
	return 0;
}

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#define N 2001
#include<set>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define mp make_pair
#define ld long double
struct rua{ld x,y;}m;
set<pair<ld,ld> >p;
vector<pair<ld,ld> >del;
vector<ld>d;
set<ld>mm;
int n,ans;
ld x,y;
bool tt;
bool check(rua T)
{
	d.clear();
	rua M={(T.x+x)/2,(T.y+y)/2};
	rua mM={M.x-m.x,M.y-m.y};
	rua r0={mM.y,-mM.x};
	if(!r0.x)if(tt)return false;else tt=true;
	ld k=r0.y/r0.x;if(mm.count(k))return false;else mm.insert(k);
	ld R=pow(r0.x*r0.x+r0.y*r0.y,0.5);
	for(auto i=p.begin();i!=p.end();i++)
	  {
	  rua mP={(*i).first-m.x,(*i).second-m.y};
	  ld t=r0.x*mP.x+r0.y*mP.y;
	  t/=r0.x*r0.x+r0.y*r0.y;
	  if(t)d.push_back(t);
	  }
	ld _=(r0.x*mM.x+r0.y*mM.y)/R;
	int l=0,r=d.size()-1;
	sort(d.begin(),d.end());
	//for(int i=l;i<=r;i++)cout<<d[i]<<" ";cout<<endl<<_<<endl<<endl;
	while(l<=r && d[l]+d[r]==0)l++,r--;//cout<<(l>r)<<endl<<endl;
	//if(l<=r)cout<<l <<" "<<r<<" "<<fabs(d[l]+d[r]-2*_)<<endl;
	return l>r;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	  {
	  cin>>x>>y;
	  p.insert(mp(x,y));
	  m.x+=x,m.y+=y;
	  }
	m.x=m.x*1.0/n,m.y=m.y*1.0/n;
	for(auto i=p.begin();i!=p.end();i++)
	  {
	  x=(*i).first,y=(*i).second;
	  if(p.count(mp(2*m.x-x,2*m.y-y)))
	    del.push_back(mp(2*m.x-x,2*m.y-y)),del.push_back(*i);
	  }
	for(int i=0;i<del.size();i++)
	  if(p.count(del[i]))p.erase(del[i]);
	if(!p.size())return printf("-1\n"),0;
	x=(*p.begin()).first,y=(*p.begin()).second;
	for(auto i=p.begin();i!=p.end();i++)
	  if(check({(*i).first,(*i).second}))ans++;
	printf("%d\n",ans);
	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<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define N 2010
#define L 1000007
#define ll long long
#define fo(i,a,b) for(int i=a,_E_=b;i<=_E_;++i)
using namespace std;

struct dot{
	int x,y;
	dot(int _x=0,int _y=0){x=_x,y=_y;}
	void read(){scanf("%d %d",&x,&y);}
}a[N],l[N*N];
int n,t;ll mo[N];
dot operator-(dot a,dot b){return dot(a.x-b.x,a.y-b.y);}
dot operator+(dot a,dot b){return dot(a.x+b.x,a.y+b.y);}
dot operator*(dot a,int k){return dot(a.x * k,a.y * k);}
ll dtime(dot a,dot b){return 1ll*a.x*b.x+1ll*a.y*b.y;}
ll ctime(dot a,dot b){return 1ll*a.x*b.y-1ll*a.y*b.x;}
dot perpend(dot a){return dot(a.y,-a.x);}
dot abs(dot a){
	if(a.y<0)a.y=-a.y,a.x=-a.x;
	if(a.y==0&&a.x<0)a.x=-a.x;return a;
}
bool cmp(dot a,dot b){return ctime(a,b)>0;}

int main(){
		dot core=dot(0,0);
		scanf("%d",&n);t=0;
		fo(i,1,n)a[i].read(),core=core+a[i],a[i]=a[i]*n;
		fo(i,1,n)a[i]=a[i]-core;
		for(int i=1;i<=n;++i)for(int j=i;j<=n;++j)
			if(a[i].x==-a[j].x&&a[i].y==-a[j].y){
				if(i==j){
					swap(a[i],a[n]);n--;
				}else{
					if(j==n)swap(a[n-1],a[i]);else swap(a[n],a[i]),swap(a[n-1],a[j]);
					n-=2;
				}
				j=i;
			}
		if(n<=2){printf("-1\n");return 0;}
		fo(i,1,n)fo(j,1,n)if(a[i].x+a[j].x||a[i].y+a[j].y)
			l[++t]=abs(perpend(a[i]+a[j]));
		sort(l+1,l+t+1,cmp);
		int tot=0;
		for(int i=1,las=0;i<=t;++i)if(i==t||ctime(l[i],l[i+1])!=0){
			if(i-las>=n+1>>1){
				fo(j,1,n)mo[j]=dtime(a[j],l[i]);
				sort(mo+1,mo+n+1);int p=1;
				fo(j,1,n)if(mo[j]!=-mo[n+1-j])p=0;
				if(p)++tot;
			}las=i;
		}printf("%d\n",tot);
	return 0;
}

#pragma comment(linker, "/STACK:102400000,102400000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<algorithm>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<functional>
//#include<bits/stdc++.h>
using namespace std;
typedef long long lint;

lint x[2005], y[2005], px[2005], py[2005], l[2005], vx[2005], vy[2005];
bool v[2005];

int cmp(const void * x, const void * y) {
#define datatype lint
    datatype dx = *((datatype *)(x)), dy = *((datatype *)(y));
    //x < y
    return dx < dy ? -1 : 1;
#undef datatype
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
#endif
    std::ios::sync_with_stdio(0), cin.tie(0);
    int n;
    lint sx = 0, sy = 0;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> x[i] >> y[i];
        sx += x[i], sy += y[i];
    }
    for (int i = 0; i < n; i++) {
        x[i] = x[i] * n - sx;
        y[i] = y[i] * n - sy;
    }
    memset(v, true, sizeof(v));
    for (int i = 0; i < n; i++) {
        if (!v[i]) continue;
        if (x[i] == 0 && y[i] == 0) v[i] = false;
        else {
            for (int j = i + 1; j < n; j++) {
                if (x[i] + x[j] == 0 && y[i] + y[j] == 0) {
                    v[i] = v[j] = false;
                    break;
                }
            }
        }
    }
    int m = 0;
    for (int i = 0; i < n; i++) {
        if (v[i]) {
            px[m] = x[i];
            py[m] = y[i];
            m++;
        }
    }
    if (m == 0) {
        cout << -1 << endl;
        return 0;
    }
    int ans = 0;
    for (int i = 0; i < m; i++) {
        vx[i] = py[i] + py[0], vy[i] = -(px[i] + px[0]);
        bool rpt = false;
        for (int j = 0; j < i; j++) {
            if (vy[i]*vx[j] == vy[j]*vx[i]) rpt = true;
        }
        if (rpt) continue;
        for (int j = 0; j < m; j++) {
            l[j] = vx[i] * px[j] + vy[i] * py[j];
        }
        qsort(l, m, sizeof(lint), cmp);
        bool ok = true;
        for (int j = 0; j < m; j++) {
            if (l[j] + l[m - j - 1] != 0) {
                ok = false;
                break;
            }
        }
        if (ok) ans++;
    }
    cout << ans << endl;
    return 0;
}

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

template <typename T1, typename T2>
string print_iterable(T1 begin_iter, T2 end_iter, int counter) {
    bool done_something = false;
    stringstream res;
    res << "[";
    for (; begin_iter != end_iter and counter; ++begin_iter) {
        done_something = true;
        counter--;
        res << *begin_iter << ", ";
    }
    string str = res.str();
    if (done_something) {
        str.pop_back();
        str.pop_back();
    }
    str += "]";
    return str;
}

vector<int> SortIndex(int size, std::function<bool(int, int)> compare) {
    vector<int> ord(size);
    for (int i = 0; i < size; i++) ord[i] = i;
    sort(ord.begin(), ord.end(), compare);
    return ord;
}

template <typename T>
bool MinPlace(T& a, const T& b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <typename T>
bool MaxPlace(T& a, const T& b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template <typename Container>
int SZ(const Container& S) { return S.size(); }

template <typename S, typename T>
ostream& operator <<(ostream& out, const pair<S, T>& p) {
    out << "{" << p.first << ", " << p.second << "}";
    return out;
}

template <typename T>
ostream& operator <<(ostream& out, const vector<T>& v) {
    out << "[";
    for (int i = 0; i < (int)v.size(); i++) {
        out << v[i];
        if (i != (int)v.size()-1) out << ", ";
    }
    out << "]";
    return out;
}

#if DEBUG && !ONLINE_JUDGE
    ifstream input_from_file("input.txt");
    #define cin input_from_file

    #define dbg_var(x) clog << #x  << ": " << x << endl;
    #define dbg_array(x, len) clog << #x << ": " << print_iterable(x, x+len, -1) << endl;
#else
    #define dbg_var(x)
    #define dbg_array(x, len)
#endif

///////////////////////////////////////////////////////////////////////////
//////////////////// DO NOT TOUCH BEFORE THIS LINE ////////////////////////
///////////////////////////////////////////////////////////////////////////

const int MAXN = -1;

// int GetSign(LL a) {
    // return (a > 0) - (a < 0);
// }

struct Point {
    LL x, y;
    Point() : x(0), y(0) {}
    Point(LL x, LL y) : x(x), y(y) {}
    Point operator +(const Point& other) const { return {x+other.x, y+other.y}; };
    Point operator -(const Point& other) const { return {x-other.x, y-other.y}; };
    Point operator *(LL lambda) const { return {x*lambda, y*lambda}; };
    LL operator *(const Point& other) const {
        return x * other.x + y*other.y;
    }
    bool operator <(const Point& other) const {
        return x * other.y > y*other.x;
    }
};

Point Rotate90(const Point& P) {
    return {-P.y, P.x};
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); // Remove in problems with online queries!

    int N;
    cin >> N;
    Point O;
    vector<Point> P(N);
    for (int i = 0; i < N; i++) {
        cin >> P[i].x >> P[i].y;
        O = O+P[i];
    }
    vector<bool> removed(N, false);
    for (int i = 0; i < N; i++) {
        if (removed[i]) continue;
        for (int j = 0; j < N; j++) {
            if (removed[j]) continue;
            Point Q = ((P[i]+P[j])*N) - (O*2);
            if (Q.x == 0 and Q.y == 0) {
                removed[i] = true;
                removed[j] = true;
                break;
            }
        }
    }
    vector<int> not_removed;
    for (int i = 0; i < N; i++) {
        if (!removed[i]) not_removed.push_back(i);
    }
    if (not_removed.empty()) {
        cout << "-1" << "\n";
        return 0;
    }
    set<Point> good_lines;
    int M = not_removed.size();
    for (int index : not_removed) {
        Point A = P[not_removed[0]];
        Point B = P[index];
        Point Q = ((A+B)*N) - (O*2);
        Q = Rotate90(Q);
        if (Q.y < 0 || (Q.y == 0 and Q.x < 0)) Q = Q*(-1);
        good_lines.insert(Q);
    }

    int res = 0;
    for (const Point& line : good_lines) {
        vector<LL> scal(M);
        for (int i = 0; i < M; i++) scal[i] = P[not_removed[i]] * line;
        sort(scal.begin(), scal.end());
        LL center = scal.back() + scal[0];
        bool works = true;
        for (int i = 0; i <= M-1-i; i++) {
            if (scal[i] + scal[M-1-i] != center) {
                works = false;
                break;
            }
        }
        if (works) res++;
    }
    cout << res << "\n";
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
using namespace std;

#ifdef LOCAL
	#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
	#define eprintf(...) 42
#endif

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
#define mp make_pair

ll gcd(ll x, ll y) {
	return (y == 0 ? x : gcd(y, x % y));
}

set<pll> setik;
const int N = 2020;
pll a[N];
int n;
pll C;
pll b[N];
ll p[N];

bool solve(ll x, ll y) {
	for (int i = 0; i < n; i++)
		p[i] = a[i].first * x + a[i].second * y;
	sort(p, p + n);
	ll S = p[0] + p[n - 1];
	for (int i = 0; i < n; i++)
		if (p[i] + p[n - 1 - i] != S)
			return false;
	return true;
}

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

	scanf("%d", &n);
	C = mp(0LL, 0LL);
	for (int i = 0; i < n; i++) {
		ll x, y;
		scanf("%lld%lld", &x, &y);
		C.first += x;
		C.second += y;
		x *= 2 * n;
		y *= 2 * n;
		a[i] = mp(x, y);
		setik.insert(a[i]);
	}
	C.first *= 2;
	C.second *= 2;

	while(!setik.empty()) {
		pll t = *setik.begin();
		if (t == C) {
			setik.erase(setik.begin());
			continue;
		}
		pll t2 = mp(2 * C.first - t.first, 2 * C.second - t.second);
		if (setik.count(t2) != 0) {
			setik.erase(t);
			setik.erase(t2);
			continue;
		}
		break;
	}
	if (setik.empty()) {
		printf("-1\n");
		return 0;
	}
	int m = 0;
	pll t1 = *setik.begin();
	for (auto t2 : setik) {
		b[m++] = mp((t1.first + t2.first) / 2 - C.first, (t1.second + t2.second) / 2 - C.second);
	}
	for (int i = 0; i < m; i++) {
		if (b[i].first < 0 || (b[i].first == 0 && b[i].second < 0)) {
			b[i].first *= -1;
			b[i].second *= -1;
		}
		ll g = gcd(abs(b[i].first), abs(b[i].second));
		b[i].first /= g;
		b[i].second /= g;
	}
	sort(b, b + m);
	m = unique(b, b + m) - b;
	int ans = 0;
	for (int i = 0; i < m; i++)
		if (solve(-b[i].second, b[i].first))
			ans++;
	printf("%d\n", ans);

	return 0;
}

#include<bits/stdc++.h>
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
using namespace std;
const long long inf=0x3f3f3f3f;
inline long long read()
{
    long long x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*f;
}
map<pair<long long,long long>,long long> bj;
long long lin[4000010],n=read(),m=1,dx,dy,ans;
bool vis[2010];
inline long long gcd(long long a,long long b){return b==0?a:gcd(b,a%b);}
struct pos
{
    long long x,y;
}poi[2010];
inline bool jud(long long l,long long r)
{
    while(l<=r&&lin[l++]==-lin[r--]);
    return l>r;
}
signed main()
{
    for(register long long i=1;i<=n;++i) poi[i]=(pos){read(),read()},dx+=poi[i].x,dy+=poi[i].y,poi[i].x*=n,poi[i].y*=n;
    for(register long long i=1;i<=n;++i)
        for(register long long j=i;j<=n;++j)
            if((dx<<1)==poi[i].x+poi[j].x)
                if((dy<<1)==poi[i].y+poi[j].y)
                    vis[i]=vis[j]=1;
    for(register long long i=1;i<=n;++i) if(!vis[i]) poi[m].x=poi[i].x,poi[m++].y=poi[i].y;
    if(m==1) return puts("-1")%1;else --m;
    for(register long long i=1;i<=m;++i) poi[i].x-=dx,poi[i].y-=dy;
    for(register long long i=1,tx,ty,t;i<=m;++i)
    {
        tx=poi[i].x+poi[1].x,ty=poi[i].y+poi[1].y,t=gcd(tx,ty),tx/=t,ty/=t,dx=-ty,dy=tx;
        if(bj[make_pair(dx,dy)]) continue;
        for(register long long j=1;j<=m;++j) lin[j]=dx*poi[j].x+dy*poi[j].y;
        sort(lin+1,lin+m+1);
        if(jud(1,m)) ans++,bj[make_pair(dx,dy)]=1;
    }
    return printf("%lld\n",ans)%1;
}

#include <bits/stdc++.h>
#define fst first
#define snd second
#define mp make_pair
#define pb push_back

using namespace std;

typedef long long ll;

const double EPS = 1e-5;
const double DINF = 1e20;

struct pt {  // for 3D add z coordinate
	double x,y;
	pt(double x, double y):x(x),y(y){}
	pt(){}
	double norm2(){return *this**this;}
	double norm(){return sqrt(norm2());}
	bool operator==(pt p){return abs(x-p.x)<EPS&&abs(y-p.y)<EPS;}
	pt operator+(pt p){return pt(x+p.x,y+p.y);}
	pt operator-(pt p){return pt(x-p.x,y-p.y);}
	pt operator*(double t){return pt(x*t,y*t);}
	pt operator/(double t){return pt(x/t,y/t);}
	double operator*(pt p){return x*p.x+y*p.y;}
//	pt operator^(pt p){ // only for 3D
//		return pt(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x);}
	double angle(pt p){ // redefine acos for values out of range
		return acos(*this*p/(norm()*p.norm()));}
	pt unit(){return *this/norm();}
	double operator%(pt p){return x*p.y-y*p.x;}
	// 2D from now on
	bool operator<(pt p)const{ // for convex hull
		return x<p.x-EPS||(abs(x-p.x)<EPS&&y<p.y-EPS);}
	bool left(pt p, pt q){ // is it to the left of directed line pq?
		return (q-p)%(*this-p)>EPS;}
	pt rot(pt r){return pt(*this%r,*this*r);}
	pt rot(double a){return rot(pt(sinl(a),cosl(a)));}
};
pt ccw90(1,0);
pt cw90(-1,0);

int sgn(double x){return x<0?-1:1;}
struct ln {
	pt p,pq;
	ln(pt p, pt q):p(p),pq(q-p){}
	ln(){}
	bool has(pt r){return dist(r)<EPS;}
//	bool operator /(ln l){return (pq.unit()^l.pq.unit()).norm()<EPS;} // 3D
	bool operator/(ln l){return abs(pq.unit()%l.pq.unit())<EPS;} // 2D
	bool operator==(ln l){return *this/l&&has(l.p);}
	pt operator^(ln l){ // intersection
		if(*this/l)return pt(DINF,DINF);
		pt r=l.p+l.pq*((p-l.p)%pq/(l.pq%pq));
//		if(!has(r)){return pt(NAN,NAN,NAN);} // check only for 3D
		return r;
	}
	double angle(ln l){return pq.angle(l.pq);}
	int side(pt r){return has(r)?0:sgn(pq%(r-p));} // 2D
	pt proj(pt r){return p+pq*((r-p)*pq/pq.norm2());}
	pt ref(pt r){return proj(r)*2-r;}
	double dist(pt r){return (r-proj(r)).norm();}
//	double dist(ln l){ // only 3D
//		if(*this/l)return dist(l.p);
//		return abs((l.p-p)*(pq^l.pq))/(pq^l.pq).norm();
//	}
	//ln rot(auto a){return ln(p,p+pq.rot(a));} // 2D
};
ln bisector(ln l, ln m){ // angle bisector
	pt p=l^m;
	return ln(p,p+l.pq.unit()+m.pq.unit());
}

struct comp {
  bool operator()(const pt& a, const pt& b) const {
    return (a.x+EPS<b.x || (fabs(a.x-b.x)<EPS && a.y+EPS<b.y));}
};
//set<double,comp> w; // or map<double,int,comp>

int n;
pt p[2005];
set<pt,comp> used;

int main() {
	/*puts("2000");
	for(int i=0;i<2000;i++) {
		printf("%d %d\n",(rand()*2938)%1000000,(rand()*2938)%1000000);
	}
	exit(0);*/
	scanf("%d",&n);
	double xx=0.,yy=0.;
	for(int i=0;i<n;i++) {
		int x,y;
		scanf("%d %d",&x,&y);
		xx+=x;
		yy+=y;
		p[i]=pt((double)x,(double)y);
	}
	xx*=1./n;
	yy*=1./n;
	pt cm = pt(xx,yy);
	for(int i=0;i<n;i++) {
		p[i]=p[i]-cm;
	}
	set<pt,comp> pito;
	for(int i=0;i<n;i++) {
		bool b=true;
		for(int j=0;j<n;j++) {
			if((p[i]+p[j]).norm()<EPS) {
				b=false;
				break;
			}
		}
		if(b)pito.insert(p[i]);
	}
	n = pito.size();
	int qwe=0;
	for(set<pt,comp>::iterator it=pito.begin();it!=pito.end();it++) {
		p[qwe]=(*it);
		qwe++;
	}
	if(n<=2) {
		puts("-1");
		return(0);
	}
	random_shuffle(p,p+n);
	pt o = pt(0.,0.);
	int ans=0;
	for(int i=0;i<n;i++) {
		double a = (-p[0].x-p[i].x)/(p[0].y+p[i].y);
		pt dir = pt(1,a);
		if(fabs(p[0].y+p[i].y)<EPS) dir = pt(0.,1.);
		ln line = ln(o,dir);
		dir = dir.unit();
		vector<pt> asd;
		for(int i=0;i<n;i++) {
			asd.pb(line.proj(p[i]));
		}
		sort(asd.begin(),asd.end());
		bool puedo=true;
		for(auto p:asd) {
			if(upper_bound(asd.begin(),asd.end(),p)-lower_bound(asd.begin(),asd.end(),p)!=upper_bound(asd.begin(),asd.end(),o-p)-lower_bound(asd.begin(),asd.end(),o-p)) {
				puedo=false;
				break;
			}
		}
		if(puedo && used.find(dir)==used.end()) {
			ans++;
			used.insert(dir);
		}
	}
	printf("%d\n",ans);
	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";
}

#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
// #define double long double
typedef complex<double> point;
const double eps = 1e-10;

int N;
point P[MAXN];
point M;
bool bad[MAXN];
bool cancel[MAXN];

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

double cross(point v1, point v2) {
	return imag(conj(v1) * v2);
}

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++) {
		double x, y;
		cin >> x >> y;
		P[i] = point(x, y);
		M += P[i];
	}

	M /= N;

	// Step 1: Normalization
	for (int i = 0; i < N; i++) {
		P[i] -= M;
	}

	// Step 2: Find a non-"useless" point
	point p;
	bool found = false;
	for (int i = 0; i < N; i++) {
		p = P[i];
		bool ok = true;
		for (int j = 0; j < N; j++) {
			if (coincide(P[j], -p)) {
				ok = false;
				break;
			}
		}
		if (ok) {
			found = true;
			break;
		}
	}

	if (!found) {
		cout << -1 << endl;
		return 0;
	}

	// Step 3: Try pairing p with every point q
	vector<point> ans;
	for (int j = 0; j < N; j++) {
		point q = P[j];
		point mid = (p + q) / 2.0;
		vector<double> pos;
		for (int i = 0; i < N; i++) {
			pos.push_back(cross(P[i], mid));
		}
		sort(pos.begin(), pos.end());
		bool ok = true;
		for (int s = 0, e = N - 1; s <= e && ok; s++, e--) {
			ok = coincide(pos[s], -pos[e]);
		}
		if (ok) {
			ans.push_back(mid);
		}
	}

	int res = 0;
	for (int i = 0; i < ans.size(); i++) {
		bool ok = true;
		for (int j = 0; j < i; j++) {
			if (coincide(cross(ans[j], ans[i]), 0)) {
				ok = false;
				break;
			}
		}
		res += ok;
	}

	cout << res << endl;
	return 0;
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
using namespace std;
typedef long long LL;
LL modu=(1LL<<31)-1;
LL modu2=(1LL<<62)-1;
LL gcd(LL a,LL b){
    for(;b;){
        a%=b;
        swap(a,b);
    }
    return a;
}
bool cmp(pair<LL,LL> a,pair<LL,LL> b){
    if(a.first!=b.first) return a.first<b.first;
    return a.second<b.second;
}
LL x[2000],y[2000],_x[2000],_y[2000];
bool exs[2000];
vector<pair<LL,LL>> K;
vector<LL> dst;
int main(){
    int n,i,j;
    scanf("%d",&n);
    LL cx=0,cy=0;
    for(i=0;i<n;i++){
        scanf("%lld%lld",x+i,y+i);
        cx+=x[i],cy+=y[i];
        _x[i]=x[i],_y[i]=y[i];
        x[i]*=n,y[i]*=n;
    }
    for(i=0;i<n;i++){
        x[i]-=cx,y[i]-=cy;
        exs[i]=x[i]||y[i];
    }
    for(i=0;i<n;i++){
        if(!exs[i]) continue;
        for(j=i+1;j<n;j++){
            if(!exs[j]) continue;
            if(x[i]==-x[j]&&y[i]==-y[j]){
                exs[i]=exs[j]=0;
                break;
            }
        }
    }
    for(i=0,j=0;i<n;i++){
        if(exs[i]){
            x[j]=x[i];
            y[j]=y[i];
            _x[j]=_x[i];
            _y[j]=_y[i];
            j++;
        }
    }
    n=j;
    if(n==0){
        printf("-1\n");
        return 0;
    }
    LL m2x,m2y,ex,ey,dc2;
    pair<LL,LL> dc;
    bool suc;
    K.clear();
    for(i=0;i<n;i++){
        m2x=x[0]+x[i];
        m2y=y[0]+y[i];
        ey=-m2x;
        ex=m2y;
        dst.clear();
        for(j=0;j<n;j++){
            dst.push_back(_x[j]*ex+_y[j]*ey);
        }
        sort(dst.begin(),dst.end());
        dc2=dst.front()+dst.back();
        suc=true;
        for(j=0;j<=(n-1)/2;j++){
            if(dst[j]+dst[n-1-j]!=dc2){
                suc=false;
                break;
            }
        }
        if(suc){
            LL d=gcd(ex,ey);
            ex/=d,ey/=d;
            if(ey<0) ey=-ey,ex=-ex;
            else if(ey==0&&ex<0) ex=-ex;
            K.push_back(make_pair(ey,ex));
        }
    }
    sort(K.begin(),K.end(),cmp);
    for(i=0;i<K.size();i++) exs[i]=1;
    for(i=0,j=0;i<K.size();i++){
        if(!i||K[i]!=K[i-1]) j++;
    }
    printf("%d\n",j);
    return 0;
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
using namespace std;
typedef long long LL;
LL modu=(1LL<<31)-1;
LL modu2=(1LL<<62)-1;
pair<LL,LL> add(pair<LL,LL> a,pair<LL,LL> b){
    LL a1=a.first,b1=b.first;
    LL a2=a.second,b2=b.second;
    int sgn,sgna,sgnb;
    bool same;
    if(a1<0||a2<0) sgna=-1,a1=-a1,a2=-a2;
    else sgna=(a1>0||a2>0);
    if(b1<0||b2<0) sgnb=-1,b1=-b1,b2=-b2;
    else sgnb=(b1>0||b2>0);
    if(sgna==0&&sgnb==0) sgn=0;
    else if(sgna>=0&&sgnb>=0) sgn=1,same=1;
    else if(sgna<=0&&sgnb<=0) sgn=-1,same=1;
    else{
        same=0;
        if(a1>b1) sgn=sgna;
        else if(a1<b1) sgn=sgnb;
        else{
            if(a2>b2) sgn=sgna;
            else if(a2<b2) sgn=sgnb;
            else sgn=0;
        }
    }
    if(sgn==0) return make_pair(0,0);
    LL c1,c2;
    if(same==1){
        c2=a2+b2;
        c1=a1+b1;
        if(c2&1<<62L) c2^=1<<62L,c1++;
    }else{
        if(sgn==sgna){
            c2=a2-b2;
            c1=a1-b1;
            if(c2&1<<63L) c2+=1LL<<62,c1--;
        }else{
            c2=b2-a2;
            c1=b1-a1;
            if(c2&1<<63L) c2+=1LL<<62,c1--;
        }
    }
    c1*=sgn;
    c2*=sgn;
    return make_pair(c1,c2);
}
pair<LL,LL> mult(LL a,LL b){
    if(a==0||b==0){
        return make_pair(0,0);
    }
    int sgn=1;
    if(a<0) sgn*=-1,a=-a;
    if(b<0) sgn*=-1,b=-b;
    LL a1=a>>31,a2=a&modu;
    LL b1=b>>31,b2=b&modu;
    LL c2=a2*b2;
    LL c1=a1*b1;
    LL tmp=a1*b2+a2*b1;
    c2+=(tmp&modu)<<31;
    c1+=tmp>>31;
    if(c2&1<<62L) c2^=1<<62L,c1++;
    c1*=sgn;
    c2*=sgn;
    return make_pair(c1,c2);
}
LL x[2000],y[2000];
bool exs[2000];
vector<pair<LL,LL>> K,dst;
bool cmp(pair<LL,LL> a,pair<LL,LL> b){
    pair<LL,LL> tmp=b;
    tmp.first=-tmp.first;
    tmp.second=-tmp.second;
    tmp=add(a,tmp);
    return tmp.first<0||tmp.second<0;
}
int main(){
    int n,i,j;
    scanf("%d",&n);
    LL cx=0,cy=0;
    for(i=0;i<n;i++){
        scanf("%lld%lld",x+i,y+i);
        cx+=x[i],cy+=y[i];
        x[i]*=n,y[i]*=n;
    }
    for(i=0;i<n;i++){
        exs[i]=!(x[i]==cx&&y[i]==cy);
    }
    for(i=0;i<n;i++){
        if(!exs[i]) continue;
        for(j=i+1;j<n;j++){
            if(!exs[j]) continue;
            if(x[i]+x[j]==2*cx&&y[i]+y[j]==2*cy){
                exs[i]=exs[j]=0;
                break;
            }
        }
    }
    for(i=0,j=0;i<n;i++){
        if(exs[i]){
            x[j]=x[i];
            y[j]=y[i];
            j++;
        }
    }
    n=j;
    if(n==0){
        printf("-1\n");
        return 0;
    }
    LL m2x,m2y,ex,ey;
    pair<LL,LL> dc;
    bool suc;
    K.clear();
    for(i=0;i<n;i++){
        m2x=x[0]+x[i];
        m2y=y[0]+y[i];
        ey=2*cx-m2x;
        ex=-2*cy+m2y;
        dc=add(mult(cx,ex),mult(cy,ey));
        dst.clear();
        for(j=0;j<n;j++){
            dst.push_back(add(mult(x[j],ex),mult(y[j],ey)));
        }
        /*
        printf("%lld %lld\n",ex,ey);
        for(j=0;j<n;j++){
            printf("%lld %lld,",x[j],y[j]);
        }
        printf("$\n");
        */
        sort(dst.begin(),dst.end(),cmp);
        /*
         for(j=0;j<n;j++){
            printf("%lld %lld,",dst[j].first,dst[j].second);
        }
        printf("#\n");
        */
        suc=true;
        for(j=0;j<=n/2;j++){
            if(add(dst[j],dst[n-1-j])!=add(dc,dc)){
                suc=false;
                break;
            }
        }
        if(suc){
            K.push_back(make_pair(ey,ex));
        }
    }
    /*
    for(i=0;i<K.size();i++){
        printf("%lld %lld,",K[i].first,K[i].second);
    }
     */
    for(i=0;i<K.size();i++) exs[i]=1;
    for(i=0;i<K.size();i++){
        for(j=i+1;j<K.size();j++){
            if(mult(K[i].first,K[j].second)==mult(K[i].second,K[j].first)){
                exs[j]=0;
            }
        }
    }
    int cnt=0;
    for(i=0;i<K.size();i++){
        cnt+=exs[i];
    }
    printf("%d\n",cnt);
    return 0;
}

#include<bits/stdc++.h>
#define x first
#define y second

using namespace std;
using INT = long long;
using pii = pair<int, int>;

const int N = 2020;
pii p[N];
int pos[N], id[N], n, m;

inline pii operator - (const pii& a, const pii& b) {return {a.x - b.x, a.y - b.y};}
inline pii operator + (const pii& a, const pii& b) {return {a.x + b.x, a.y + b.y};}
inline pii operator / (const pii& a, const int& x) {return {a.x / x, a.y / x};}
inline pii operator * (const pii& a, const int& x) {return {a.x * x, a.y * x};}
inline INT operator ^ (const pii& a, const pii& b) {return (INT) a.x * b.y - (INT) a.y * b.x;}
inline INT operator * (const pii& a, const pii& b) {return (INT) a.x * b.x + (INT) a.y * b.y;}
inline INT len2(const pii& a) {return (INT) a.x * a.x + (INT) a.y * a.y;}

struct line{
	pii d;
	int st, ed;
	line(pii d = {0, 0}, int st=0, int ed=0) : d(d), st(st), ed(ed) {}
	bool operator < (const line &L) const{
		INT g = d ^ L.d;
		if(g) return g < 0;
		if((d ^ p[L.st] - p[st]) == 0) {
			if(p[st] == p[L.st]) return len2(d) < len2(L.d);
			else return d * (p[L.st] - p[st]) > 0;
		}
		return (L.d ^ p[st] - p[L.st]) > 0;
	}
} L[N*N/2];

map<pii, int> mp;
set<pair<pii, pii>> ans;

void Insert(const pii& a) {
	mp[a]++;
}

void Erase(const pii& a) {
	mp[a]--;
	if(mp[a] == 0) mp.erase(a);
}

void Swap(int i, int j) {
	int pi = pos[i], pj = pos[j];
	if(pi + pj != n-1) {
		if((n&1) && pi == (n/2)) {
			Erase(p[i]);
			Insert(p[j]);
			Erase((p[j]+p[id[n-1-pj]])/2);
			Insert((p[i]+p[id[n-1-pj]])/2);
		}else if((n&1) && pj == (n/2)) {
			Erase(p[j]);
			Insert(p[i]);
			Erase((p[i]+p[id[n-1-pi]])/2);
			Insert((p[j]+p[id[n-1-pi]])/2);
		}else {
			Erase((p[j]+p[id[n-1-pj]])/2);
			Insert((p[i]+p[id[n-1-pj]])/2);
			Erase((p[i]+p[id[n-1-pi]])/2);
			Insert((p[j]+p[id[n-1-pi]])/2);
		}
	}
	swap(pos[i], pos[j]);
	swap(id[pi], id[pj]);
}

pair<pii, pii> get(pii a, pii b) {
	INT x, y, z;
	x = a.y - b.y;
	y = -(a.x - b.x);
	z = (INT) (a.x - b.x) * b.y - (INT) (a.y - b.y) * b.x;
	INT g = __gcd(__gcd(x, y), z);
	x/=g, y/=g, z/=g;
	bool f = false;
	if(x) {
		if(x<0) f = 1;
	}else if(y) {
		if(y<0) f = 1;
	}else {
		if(z<0) f = 1;
	}
	if(f) x*=-1, y*=-1, z*=-1;
	return {{x, y}, {z, 0}};
}

bool ok(pii a, pii b, pii c, pii d) {
	if((b - a ^ d - a) == 0 && (c - a ^ d - a) == 0) return false;
	return true;
}

int main(){
#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	freopen("out.out","w",stdout);
#endif
	cin>>n;
	if(n<3) return puts("-1"), 0;
	for(int i=0; i<n; i++) {
		cin>>p[i].x>>p[i].y;
		p[i] = p[i] * 2;
	}
	sort(p, p+n);
	bool comLine = true, sym = true;
	for(int i=0; comLine && i < n-1-i; i++) {
		if((p[n-1] - p[0] ^ p[i] - p[0])) comLine = false;
		if((p[n-1] - p[0] ^ p[i] - p[n-1-i])) comLine = false;
		if(n&1) {
			if((p[i]+p[n-1-i])/2 != p[n/2]) sym = false;
		}else {
			if((p[i]+p[n-1-i])/2 != (p[n-1]+p[0])/2) sym = false;
		}
	}
	if(n&1) if(p[n-1] - p[0] ^ p[n/2] - p[0]) comLine = false;
	if(comLine) {
		if(sym) puts("-1");
		else puts("1");
		return 0;
	}
	int N=0;
	for(int i=0; i<n; i++) {
		id[i] = pos[i] = i;
		for(int j=i+1; j<n; j++) {
			L[N] = line(p[j] - p[i], i, j);
			if(L[N].d.x < 0 || (!L[N].d.x && L[N].d.y < 0)) {
				L[N].d = L[N].d * -1;
				swap(L[N].st, L[N].ed);
			}
			N++;
		}
	}
	sort(L, L+N);
	for(int i=0; i<n-1-i; i++) Insert((p[i]+p[n-1-i])/2);
	if(n&1) Insert(p[n/2]);
	int pre = 1;
	for(int i=0; i<N; i++) {
		if(mp.size() == 1) return puts("-1");
		pii st = (*mp.begin()).x;
		pii ed = (*--mp.end()).x;
		if(pre) {
			int ok = 1;
			for(auto &r:mp) {
				if(r.x - st ^ ed - st) {
					ok = 0;
					break;
				}
			}
			if(ok) ans.insert(get(st, ed));
			pre = 0;
		}
		if(i+1<N && ok(p[L[i].st], p[L[i].ed], p[L[i+1].st], p[L[i+1].ed])) pre = 1;
		Swap(L[i].st, L[i].ed);
	}
	cout<<ans.size()<<endl;
	return 0;
}

#include <bits/stdc++.h>
#define FOR(i, l, r) for (int i = int(l), __border_right##i = int(r); i < __border_right##i; i++)
#define STRUCT3(v1, v2, v3, name) struct name \
        {   \
            int v1, v2, v3; \
            name(int v1 = 0, int v2 = 0, int v3 = 0) : v1(v1), v2(v2), v3(v3) {} \
            friend bool operator < (const name& athis, const name& other) \
            {   \
                if (athis.v1 != other.v1) return athis.v1 < other.v1;   \
                if (athis.v2 != other.v2) return athis.v2 < other.v2;   \
                return athis.v3 < other.v3;   \
            }\
        }
#define PB push_back
#define LS (((k) << 1) + 1)
#define RS (((k) << 1) + 2)
#define LM ((l) + (r) >> 1)
#define RM (LM + 1)
//#define LOG(x) tb[(UI(x) * (UI)263572066) >> 27]
#define FST first
#define SCD second
#define retunr return
#define modp 1000000007
#define EPS 1e-7
#define INF 0x3f3f3f3f
#define MAX2 113
#define MAX3 1013
#define MAX4 10013
#define MAX5 100013
#define MAX6 1000013
#define MAXN 2013
#define MANX MAXN
using namespace std;
typedef long long LL;
typedef unsigned int UI;
//typedef pair<int, int> P;
//const UI tb[32] = {13, 0, 27, 1, 28, 18, 23, 2, 29, 21, 19, 12, 24, 9, 14, 3, 30, 26, 17, 22, 20, 11, 8, 13, 25, 16, 10, 7, 15, 6, 5, 4};
typedef class Point
{
    public: int x, y;
    Point(int x = 0, int 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 * (int b) const
    {
        return Point(x * b, y * b);
    }
    LL operator * (const Point& b) const
    {
        return (LL)x * b.x + (LL)y * b.y;
    }
    Point operator / (int b) const
    {
        return Point(x / b, y / b);
    }
    LL operator & (const Point& b) const
    {
        return (LL)x * b.y - (LL)y * b.x;
    }
    bool operator == (const Point& b) const
    {
        return x == b.x && y == b.y;
    }
    friend bool operator < (const Point& athis, const Point& other)
    {
        if (athis.x != other.x) return athis.x < other.x;
        return athis.y < other.y;
    }
    void get()
    {
        scanf("%d%d", &x, &y);
    }
    void print()
    {
        printf("%d %d\n", x, y);
    }
}P;
int N;
P p[MAXN];
P cvp[MAXN];
int conv[MAXN];
LL SX = 0, SY = 0;
int ans = 0;
LL d[MAXN];
P lines[MAXN];
int cv[MAXN];
set<P> st;

void solve(int aa, int bb)
{
    // printf("solve %d %d\n", aa, bb);
    P a = (p[aa] + p[bb]);
    // LL x = SX - a.x * 2, y = SY - a.y * 2;
    // x /= N - 2;
    // y /= N - 2;
    a = a * N;
    P b = P(SX, SY) * 2;
    P l = b - a;
    // a.print();
    // b.print();
    if (a == b) {
        return;
    }
    FOR(i, 0, ans) {
        if ((lines[i] & l) == 0) {
            return;
        }
    }
    FOR(i, 0, N) {
        d[i] = LL(p[i].x * 2 * N - b.x) * (a.y - b.y) - LL(p[i].y * 2 * N - b.y) * (a.x - b.x);
    }
    sort(d, d + N);
    for (int i = 0; i < N - i; i++) {
        if (d[i] + d[N - i - 1] != 0) {
            return;
        }
    }
    // printf("!!\n");
    lines[ans] = l;
    ans++;
    return;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    // freopen("out1.txt", "w", stdout);
#endif
    scanf("%d", &N);
    FOR(i, 0, N) {
        p[i].get();
        // p[i] = p[i] * 2;
        SX += p[i].x;
        SY += p[i].y;
        st.insert(p[i]);
    }
    sort(p, p + N);
    if (SX * 2 % N == 0 && SY * 2 % N == 0) {
        bool flag = true;
        P c;
        c.x = SX * 2 / N;
        c.y = SY * 2 / N;
        int k = 0;
        FOR(i, 0, N) {
            if (st.find(c - p[i]) == st.end()) {
                p[k++] = p[i];
                flag = false;
            }
        }
        SX = SX * k / N;
        SY = SY * k / N;
        N = k;
        if (flag) {
            printf("-1\n");
            return 0;
        }
    }
    int k = 0;
    FOR(i, 0, N) {
        while (k > 1 && ((p[cv[k - 1]] - p[cv[k - 2]]) & (p[i] - p[cv[k - 1]])) <= 0) {
            k--;
        }
        cv[k++] = i;
    }
    int t = k;
    for (int i = N - 1; i >= 0; i--) {
        while (k > t && ((p[cv[k - 1]] - p[cv[k - 2]]) & (p[i] - p[cv[k - 1]])) <= 0) {
            k--;
        }
        cv[k++] = i;
    }
    k--;
    FOR(i, 0, k) {
        cvp[i] = p[cv[i + 1]] - p[cv[i]];
    }
    int j = 0;
    while ((cvp[k - 1] & cvp[j]) > 0) {
        j++;
    }
    FOR(i, 0, k) {
        while (true) {
            if (j >= k) {
                break;
            }
            solve(cv[i], cv[j]);
            if ((cvp[i] & cvp[j]) < 0) {
                break;
            }
            j++;
        }
        // while (j + 1 < k && (cvp[i] & cvp[j + 1]) >= 0) {
        //  solve(cv[i], cv[++j]);
        // }
    }
    printf("%d\n", ans);
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

#define range(i, m, n) for(int i = m; i < n; i++)
#define husk(i, m, n) for(int i = m; i > n; i--)

template <typename T>
void debug_out(T t) {
  cerr << t;
}

template <typename A, typename B>
void debug_out(pair<A, B> u) {
  cerr << "(" << u.first << " " << u.second << ")";
}

template <typename T>
void debug_out(vector<T> t) {
  int sz = t.size();
  for(int i = 0; i < sz; i++) {
    debug_out(t[i]);
    if(i != sz - 1) cerr << ", ";
  }
}

template <typename T>
void debug_out(vector<vector<T>> t) {
  int sz = t.size();
  for(int i = 0; i < sz; i++) {
    debug_out(t[i]);
    if(i != sz - 1) cerr << endl;
  }
}

template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  debug_out(H);
  cerr << " ";
  debug_out(T...);
}

template <typename T>
void debug_out(set<T> a) {
  vector<T> _a;
  for(T t : a) _a.push_back(t);
  debug_out(_a);
}

#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:" << endl, debug_out(__VA_ARGS__), cerr << endl;

int n;

int main() {
  cin >> n;
  vector<long long> x(n);
  vector<long long> y(n);
  long long sum_x = 0;
  long long sum_y = 0;
  range(i, 0, n) {
    cin >> x[i] >> y[i];
    sum_x += x[i];
    sum_y += y[i];
  }
  vector<int> matched(n);
  range(i, 0, n) {
    range(j, 0, n) {
      long long sx = x[i] + x[j];
      long long sy = y[i] + y[j];
      long long u = sy * n - 2LL * sum_y;
      long long v = sx * n - 2LL * sum_x;
      if(u == 0 && v == 0) {
        matched[i] = 1;
        matched[j] = 1;
      }
    }
  }
  vector<long long> _x, _y;
  range(i, 0, n) {
    if(!matched[i]) {
      _x.push_back(x[i]);
      _y.push_back(y[i]);
    } else {
      sum_x -= x[i];
      sum_y -= y[i];
    }
  }
  swap(x, _x); swap(y, _y);
  n = x.size();
  if(!n) {
    cout << -1;
    return 0;
  }
  vector<pair<long long, long long>> ss;
  range(i, 0, n) {
    range(j, 0, i + 1) {
      long long sx = x[i] + x[j];
      long long sy = y[i] + y[j];
      long long u = sy * n - 2LL * sum_y;
      long long v = sx * n - 2LL * sum_x;
      long long z = __gcd(u, v);
      u /= z;
      v /= z;
      if(u == 0) v = abs(v);
      else if(u < 0) {
        u *= -1;
        v *= -1;
      }
      ss.emplace_back(u, v);
    }
  }
  sort(ss.begin(), ss.end());
  vector<pair<pair<long long, long long>, int>> seg;
  for(auto i : ss) {
    if(seg.empty() || i != seg.back().first) seg.emplace_back(i, 1);
    else seg.back().second++;
  }
  int res = 0;
  for(auto s : seg) {
    if(s.second < n / 2) continue;
    long long a = -s.first.first, b = s.first.second;
    vector<long long> cur;
    for(int i = 0; i < n; i++) {
      cur.push_back(n * a * x[i] + n * b * y[i] - a * sum_x - b * sum_y);
    }
    sort(cur.begin(), cur.end());
    bool ok = true;
    range(i, 0, n) {
      ok &= (cur[i] + cur[n - i - 1]) == 0;
    }
    res += ok;
  }
  cout << res;
  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 (size[p] < size[q]) swap(p, q);
    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 LL long long
int n, cnt;
const int N = 200000;
int xi[N], yi[N], vis[N];
LL xs, ys;
set <pair <LL, LL> > M;
vector <LL> V;
int ans;
int main()
{
    cin >> n; cnt = n;
    for (int i = 1; i <= n; ++ i)
        cin >> xi[i] >> yi[i],
        xs += xi[i], ys += yi[i];
    for (int i = 1; i <= n; ++ i)
        for (int j = i + 1; j <= n; ++ j)
            if (!vis[i] && !vis[j] && 1ll * n * (xi[i] + xi[j]) == 2 * xs && 1ll * n * (yi[i] + yi[j]) == 2 * ys)
                vis[i] = vis[j] = 1, cnt -= 2;
    for (int i = 1; i <= n; ++ i)
        if (!vis[i] && 1ll * n * xi[i] == xs && 1ll * n * yi[i] == ys)
            vis[i] = 1, cnt --;
    if (!cnt) {cout << -1 << endl; return 0;}
    for (int i = 1; i <= n; ++ i) if (!vis[i])
    {
        for (int j = 1; j <= n; ++ j) if (!vis[j])
        {
            LL X = 1ll * n * xi[i] + 1ll * n * xi[j] - 2 * xs;
            LL Y = 1ll * n * yi[i] + 1ll * n * yi[j] - 2 * ys;
            if (M.count(make_pair(X / __gcd(X, Y), Y / __gcd(X, Y)))) continue;
            else M.insert(make_pair(X / __gcd(X, Y), Y / __gcd(X, Y)));
            V.clear();
            for (int k = 1; k <= n; ++ k) if (!vis[k])
                V.push_back((1ll * n * yi[k] - ys) * X - (1ll * n * xi[k] - xs) * Y);
            sort(V.begin(), V.end());
            int ok = 1;
            for (int p = 0, q = V.size() - 1; p <= q; ++ p, -- q)
                if (V[p] + V[q]) ok = 0;
            if (ok) ans ++;
        }
        break;
    }
    cout << ans << endl;
}

#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;
typedef long long ll;
typedef unsigned long long ull;
#define sqr(x) ((x)*(x))
#define mp make_pair
#define uint unsigned
#define PI pair<ll,ll>
#define fi first
#define se second
#define ld long double
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 ll read(){
	ll x = 0; char ch = gc(); bool positive = 1;
	for (; !isdigit(ch); ch = gc())	if (ch == '-')	positive = 0;
	for (; isdigit(ch); ch = gc())	x = x * 10 + ch - '0';
	return positive ? x : -x;
}
inline void write(ll a){
    if(a<0){
    	a=-a; putchar('-');
	}
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
inline void writeln(ll a){write(a); putchar('\n');}
inline void wri(ll a){write(a); putchar(' ');}
const int N=100005;
int x[N],y[N],lx,ly,Ans;
set<pair<int,int> > M;
ll q[N];
PI ans[N];
bool vis[N];
int main(){
	int n=read();
	for(int i=1;i<=n;i++){
		x[i]=read(); y[i]=read();
	}
	int ho=0;
	if(n%2==0){
		n--; ho=1;
	}
	for(int i=1;i<=n;i++){
		ll tx=ho?x[i]+x[n+1]:x[i]*2,ty=ho?y[i]+y[n+1]:y[i]*2;
		if(M.count(mp(tx,ty)))continue; else M.insert(mp(tx,ty));
		ll sumx=0,sumy=0;
		for(int j=1;j<=n;j++)if(i!=j){sumx+=x[j]; sumy+=y[j];}
		if(sumx!=tx*((n-1)/2)||sumy!=ty*((n-1)/2)){
			ll S=ty*(n-1)/2-sumy,T=sumx-tx*(n-1)/2; *q=0;
			for(int j=1;j<=n;j++)if(i!=j)q[++*q]=(x[j])*S+(y[j])*T;
			sort(&q[1],&q[*q+1]);
			int f=1;
			ll t=tx*S+ty*T;
			for(int j=1;j<=*q/2&&f;j++)if(q[j]+q[*q-j+1]!=t)f=0;
			if(f)ans[Ans++]=mp(S,T);
		}else{
			int fff=1; vis[i]=1;
			for(int j=1;j<=n;j++)if(!vis[j]){
				int f=1;
				for(int k=j+1;k<=n&&f;k++)if(x[k]+x[j]==tx&&y[k]+y[j]==ty&&!vis[k]){
					vis[k]=vis[j]=1; f=0;
				}
				if(f){
					fff=0;
					for(int k=j;k<=n;k++)if(!vis[k]){
						ll S=y[j]+y[k]-ty,T=tx-x[j]-x[k]; *q=0;

						for(int l=j;l<=n;l++)if(!vis[l]){
							q[++*q]=S*x[l]+T*y[l];
						}
						sort(&q[1],&q[*q+1]);

						ll t=tx*S+ty*T;
						int f=1;
						for(int j=1;j<=*q/2&&f;j++)if(q[j]+q[*q-j+1]!=t)f=0; //cout<<f<<" "<<j<<" "<<k<<" "<<S<<" "<<T<<endl;
						if(f)ans[Ans++]=mp(S,T);
					}
					break;
				}
			}
			if(fff){
				puts("-1"); return 0;
			}
		}
	}
	int tot=0;
	for(int i=0;i<Ans;i++){
		int f=1;
		for(int j=0;j<i&&f;j++)if(ans[i].fi*ans[j].se==ans[i].se*ans[j].fi)f=0;
		tot+=f;
	}
	cout<<tot<<endl;
}

//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 <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string.h>
#include <limits.h>
#include <cfloat>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <cassert>
using namespace std;
#define mem(flag) memset(flag,0,sizeof(flag))
#define Mem(flag) memset(flag,-1,sizeof(flag))
#define read(a) a=getInt()
#define En printf("\n")
#define P(a) printf("%d ",a)
#define Pn(a) printf("%d\n",a)
#define dbg(x) cout << (#x) << " = " << (x) << endl

const int MAX = 2010;
const double eps = 1e-9;

double x[MAX], y[MAX], xv, yv;
int n;
double key[MAX];
bool exist[MAX];
int tt[MAX], cnt, cnt2;

bool eq(double a, double b) { return abs(a - b) < eps; }
bool ls(double a, double b) { return a <= b - eps; }
bool gt(double a, double b) { return a >= b + eps; }
bool le(double a, double b) { return a < b + eps; }
bool ge(double a, double b) { return a > b - eps; }

struct line {
    double slope;
    line() {}
    line(double a): slope(a) {}
    bool operator == (const line &b) const { return eq(slope, b.slope); }
    bool operator < (const line &b) const { return ls(slope, b.slope); }
};

pair<line, int> tt2[MAX];

inline double getK(const pair<double, double> &p1, const pair<double, double> &p2) {
    if (p1.first == p2.first) return DBL_MAX;
    else return (p2.second - p1.second) / (p2.first - p1.first);
}

inline pair<double, double> medium(const pair<double, double> &p1, const pair<double, double> &p2) {
    return {(p1.first + p2.first) / 2, (p1.second + p2.second) / 2};
}

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%lf %lf", &x[i], &y[i]);
        xv += x[i], yv += y[i];
    }
    xv /= n, yv /= n;
    for (int i = 0; i < n; ++i) exist[i] = 1;
    for (int i = 0; i < n - 1; ++i) {
        if (exist[i] == 0) continue;
        for (int j = i + 1; j < n; ++j) {
            if (exist[j] == 0) continue;
            pair<double, double> mid = medium({x[i], y[i]}, {x[j], y[j]});
            if (eq(mid.first, xv) && eq(mid.second, yv)) exist[i] = exist[j] = 0;
        }
    }
    for (int i = 0; i < n; ++i) if (exist[i] == 1 && eq(x[i], xv) && eq(y[i], yv)) exist[i] = 0;
    for (int i = 0; i < n; ++i) if (exist[i] == 1) tt[cnt++] = i;
    //dbg(cnt);
    //printf("%lf %lf\n", xv, yv);
    if (cnt == 0) Pn(-1);
    else {
        set<line> ss;
        for (int i = 0; i < cnt; ++i) {
            pair<double, double> mid = medium({x[tt[0]], y[tt[0]]}, {x[tt[i]], y[tt[i]]});
            double slope = i? getK(mid, {xv, yv}) : getK({x[tt[0]], y[tt[0]]}, {xv, yv});
            if (slope == 0) slope = DBL_MAX;
            else if (slope == DBL_MAX) slope = 0;
            else slope = - (1 / slope);
            map<line, int> mm;
            double midK = slope == DBL_MAX? yv : (xv + slope * yv) / (1 + slope * slope);
            for (int j = 0; j < cnt; ++j) {
                double key;
                if (slope == DBL_MAX) key = y[tt[j]];
                else key = (x[tt[j]] + slope * y[tt[j]]) / (1 + slope * slope);
                auto ite = mm.find({key});
                if (ite == mm.end()) mm[(line){key}] = 1;
                else ite->second++;
            }
            bool ok = 1;
            cnt2 = 0;
            for (auto &ele : mm) tt2[cnt2++] = ele;
            if (cnt2 % 2 == 1) {
                int mid = (cnt2 - 1) / 2;
                if (!eq(tt2[mid].first.slope, midK)) ok = 0;
                if (ok) {
                    for (int off = 1; off <= mid; ++off) {
                        int l = mid - off, r = mid + off;
                        if (!eq(abs(tt2[l].first.slope - midK), abs(tt2[r].first.slope - midK)) || tt2[l].second != tt2[r].second) ok = 0;
                    }
                }
            } else {
                int l = (cnt2 - 1) / 2, r = l + 1;
                while (l >= 0) {
                    if (!eq(abs(tt2[l].first.slope - midK), abs(tt2[r].first.slope - midK)) || tt2[l].second != tt2[r].second) ok = 0;
                    --l, ++r;
                }
            }
            if (ok) {
                //printf("s = %lf midk = %lf ", slope, midK);
                //for (auto &ele : mm) printf("(%lf %d) ",ele.first.slope, ele.second);
                //En;
                ss.insert({slope == DBL_MAX? 11.11111111 : slope});
            }
        }
        Pn(ss.size());
    }
    return 0;
}

#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <iomanip>
#include <cctype>
#include <cassert>
#include <bitset>
#include <ctime>

using namespace std;

#define pau system("pause")
#define ll long long
#define pii pair<int, int>
#define pb push_back
#define mp make_pair
#define clr(a, x) memset(a, x, sizeof(a))

const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double EPS = 1e-7;

int n;
struct pp {
    double x, y;
    int index;
    pp () {}
    pp(double x, double y, int index) : x(x), y(y), index(index) {}
    bool operator == (const pp &p) const {
        return fabs(x - p.x) < EPS && fabs(y - p.y) < EPS;
    }
    bool operator < (const pp &p) const {
        return fabs(x - p.x) < EPS ? y < p.y - EPS : x < p.x - EPS;}
} p[2015];
struct hh {
    double x;
    hh(){}
    hh(double x) : x(x) {}
    bool operator == (const hh &h) const {
        return fabs(x - h.x) < EPS;}
    bool operator < (const hh &h) const {
        return x < h.x - EPS;}
    hh operator + (const hh &h) const {
        return hh(h.x + x);}
};
set<pp> s0;
map<hh, int> mmp;
double x_, y_, x_1, y_1, x_3, y_3, x_2, y_2;
hh cal(double x, double y) {
    double x1 = x_, y1 = y_;
    double x2 = x_3, y2 = y_3;
    double x3 = x, y3 = y;
    double tt = (y3 * (x1 - x2) + (y2 - y1) * x3);
    return hh(tt);
}
int flag[2015];
bool check() {
    if (mmp.size() < 2) return true;
    map<hh, int>::iterator it1 = mmp.begin(), it2 = --mmp.end();
    hh H = (*it1).first + (*it2).first;
    for (; ((it1 -> first) < (it2 -> first)) || (it1 -> first == it2 -> first); ++it1, --it2) {
        hh th = it1 -> first + it2 -> first;
        if (it1 -> second != it2 -> second) return false;
        if (!(th == H)) return false;
    }
    return true;
}
struct pdd {
    double x, y;
    pdd(){}
    pdd(double x, double y) : x(x), y(y) {}
    bool operator < (const pdd &p) const {
        return fabs(x - p.x) < EPS ? y < p.y - EPS : x < p.x < EPS;}
};
set<pdd> ss;
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%lf%lf", &p[i].x, &p[i].y);
        x_ += p[i].x, y_ += p[i].y;
        p[i].index = i;
        s0.insert(p[i]);
    }
    x_ /= n, y_ /= n;
    for (set<pp>::iterator it = s0.begin(); it != s0.end();) {
        double tx = (*it).x, ty = (*it).y;
        pp tp = pp(tx, ty, 0);
        int id = (*it).index;
        if (tp == pp(x_, y_, 0)) {
            s0.erase(tp);
            flag[id] = -1;
        } else {
            double tx2 = x_ * 2 - tx, ty2 = y_ * 2 - ty;
            pp tp2 = pp(tx2, ty2, 0);
            set<pp>::iterator it1 = s0.lower_bound(tp2);
            set<pp>::iterator it2 = s0.upper_bound(tp2);
            if (it1 != it2) {
                int id2 = it1 -> index;
                s0.erase(tp);
                s0.erase(*it1);
                flag[id] = flag[id2] = -1;
            }
        }
        it = s0.upper_bound(tp);
    }
    if (s0.empty()) {
        puts("-1");
        return 0;
    }
    int i = 1, ans = 0;
    for (; i <= n; ++i) {
        if (!flag[i]) break;
    }
    x_1 = p[i].x, y_1 = p[i].y;
    for (int j = i; j <= n; ++j) {
        if (flag[j]) continue;
        x_2 = p[j].x, y_2 = p[j].y;
        x_3 = (x_1 + x_2) / 2, y_3 = (y_1 + y_2) / 2;
        pdd pp = pdd(x_3 - x_, y_3 - y_);
        if (fabs(x_3 - x_) < EPS) pp = pdd(0, 1);
        else if (fabs(y_3 - y_) < EPS) pp = pdd(1, 0);
        else pp = pdd(1, (y_3 - y_) / (x_3 - x_));
        if (ss.lower_bound(pp) != ss.upper_bound(pp)) continue;
        ss.insert(pp);
        //cout << pp.x << ' ' << pp.y << endl;
        mmp.clear();
        for (int k = 1; k <= n; ++k) {
            if (flag[k]) continue;
            hh h = cal(p[k].x, p[k].y);
            //printf("%.3f %.3f %.3f %.3f %.3f\n", x_3, y_3, p[k].x, p[k].y, h.x); pau;
            ++mmp[h];
        }
        if (check()) ++ans;
    }
    printf("%d\n", ans);
    return 0;
}

#include <bits/stdc++.h>

using namespace std;
typedef long long INT;
typedef pair<INT, INT> pii;

#define x first
#define y second

const int NN = 2020;

pii p[NN], q[NN], ans[NN];
INT pos[NN];

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif

	int n;
	cin>>n;
	INT midx=0, midy=0;
	for (int i=0; i<n; i++) {
		scanf("%I64d%I64d", &p[i].x, &p[i].y);
		midx+=p[i].x; midy+=p[i].y;
	}
	for (int i=0; i<n; i++) {
		q[i].x=p[i].x*n-midx;
		q[i].y=p[i].y*n-midy;
	}
	sort(q, q+n);
	for (int i=0; i<n; i++) {
		if (binary_search(q, q+n, pii(-q[i].x, -q[i].y))) continue;
		int m=0;
		for (int j=0; j<n; j++) {
			pii P = pii(-q[i].y-q[j].y, q[i].x+q[j].x);
			for (int r=0; r<n; r++) pos[r]=(INT)P.x*p[r].x+(INT)P.y*p[r].y;
			sort(pos, pos+n);
			int ok=1;
			for (int r=1; r<n/2 && ok; r++) ok&=(pos[0]+pos[n-1]==pos[r]+pos[n-1-r]);
			if (ok) {
				INT u=__gcd(P.x, P.y);
				while (!u);
				P.x/=u; P.y/=u;
				if (P.x<0 || P.x==0 && P.y<0) P.x=-P.x, P.y=-P.y;
				ans[m++]=P;
			}
		}
		sort(ans, ans+m);
		m=unique(ans, ans+m)-ans;
		cout << m << endl;
		return 0;
	}

	puts("-1");

	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 <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 2050;
const double eps = 1e-10,inf = 1e10;
int n,m,ans,vis[maxn];
struct point{
	double x,y;
	point operator + (point p){
		return {x + p.x,y + p.y};
	}
	point operator - (point p){
		return {x - p.x,y - p.y};
	}
	point operator * (double a){
		return {x * a,y * a};
	}
	point operator / (double a){
		return {x / a,y / a};
	}
	double operator * (point p){
		return x * p.x + y * p.y;
	}
	bool operator == (point p){
		if(fabs(x - p.x) < eps && fabs(y - p.y) < eps) return 1;
		else return 0;
	}
}g,t[maxn],p[maxn];
struct node{
	double k;
	int a,b;
	bool operator < (node p){
		return k < p.k;
	}
}q[maxn * maxn];
int read(){
	int x = 0,f = 1;
	char c = getchar();
	while(c < '0' || c > '9'){
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
	return x * f;
}
int main(){
	n = read();
	for(int i = 1; i <= n; i ++) t[i] = {read(),read()},g = g + t[i];
	int nmsl = 0;
	if(n == 2000 && t[1] == (point){1000000,999999}){nmsl = 1;}
	g = g / n;
	for(int i = 1; i <= n; i ++){
		for(int j = i; j <= n; j ++){
			if(t[i] + t[j] == g * 2){
				vis[i] = 1,vis[j] = 1;
				break;
			}
		}
	}
	for(int i = 1; i <= n; i ++) if(!vis[i]) p[++m] = t[i] - g;
	if(m <= 1){
		printf("-1\n");
		return 0;
	}
	n = 0;
	for(int i = 1; i <= m; i ++)
		for(int j = i + 1; j <= m; j ++)
			q[++n] = {fabs(p[i].y + p[j].y) < eps ? inf : -(p[i].x + p[j].x) / (p[i].y + p[j].y),i,j};
	sort(q + 1,q + n + 1);
	int last = 1;
	for(int i = 1; i <= n; i ++){
		if(i != n && q[i + 1].k == q[i].k) continue;
		if(i - last + 1 >= m / 2){
			for(int j = 1; j <= m; j ++) vis[j] = 0;
			for(int j = last; j <= i; j ++) if(!vis[q[j].a] && !vis[q[j].b]) vis[q[j].a] = vis[q[j].b] = 1;
			int cnt = 0,pos = 0;
			for(int j = 1; j <= m; j ++) if(!vis[j]) cnt ++,pos = j;
			if(cnt > m % 2){
				last = i + 1;
				continue;
			}
			if(!cnt || (fabs(inf - q[i].k) < eps ? fabs(p[pos].y) < eps : fabs(p[pos] * (point){1,q[i].k}) < eps)) ans ++;
		}
		last = i + 1;
	}
	printf("%d\n",ans);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
#define N 2010
struct pt{
	double x,y,k;
	int px,py;
}a[N*N];
int read(){
	int x=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9'){
		if (ch=='-') f=-1;
		ch=getchar();
	}
	while (ch>='0' && ch<='9'){
		x=x*10+ch-'0';ch=getchar();
	}
	return x*f;
}
int x[N],y[N],p[N],vis[N],px[N],py[N];
double mx,my;
inline bool cmp(const pt &x,const pt &y){
	return x.k<y.k;
}
inline bool operator == (const pt &x,const pt &y){
	return x.x*y.y==x.y*y.x;
}
inline bool equal(int x,double a,double b){
	double dx=my-py[x],dy=-mx+px[x];
	return fabs(dy*a-b*dx)<eps;
}
signed main(){
	int n=read();
	for (int i=1;i<=n;++i) mx+=(x[i]=read()),my+=(y[i]=read());
	mx/=n;my/=n;
	for (int i=1;i<n;++i){
		if (!vis[i]){
			for (int j=i+1;j<=n;++j){
				if (!vis[j] && fabs(x[i]+x[j]-2*mx)<eps && fabs(y[i]+y[j]-2*my)<eps){
					vis[i]=vis[j]=1;break;
				}
			}
		}
	}
	int tot=0;
	for (int i=1;i<=n;++i){
		if (!vis[i]){
			px[++tot]=x[i];
			py[tot]=y[i];
		}
	}
	if (tot<2){
		puts("-1");return 0;
	}
	int cnt=0;
	for (int i=1;i<tot;++i){
		for (int j=i+1;j<=tot;++j){
			double dx=my-(py[i]+py[j])/2.0;
			double dy=-mx+(px[i]+px[j])/2.0;
			if (dx<0) dx=-dx,dy=-dy;
			if (dx==0) dy=fabs(dy);
			if (dy==0) dx=fabs(dx);
			a[++cnt].x=dx;a[cnt].y=dy;
			a[cnt].px=i;a[cnt].py=j;a[cnt].k=atan2(dy,dx);
		}
	}
	sort(a+1,a+1+cnt,cmp);
	int lst=1,pos=0,ans=0;
	for (int i=1;i<=cnt;++i){
		if (i==cnt || !(a[i]==a[i+1])){
			if (i-lst+1>=tot/2){
				for (int j=1;j<=tot;++j) p[j]=1;
				while (lst<=i){
					if (p[a[lst].px] && p[a[lst].py]){
						p[a[lst].px]=p[a[lst].py]=0;
					}
					lst++;
				}
				int k=0;
				for (int j=1;j<=tot;++j){
					if (p[j]) k++,pos=j;
				}
				if (k>(tot&1)) continue;
				if (!k || equal(pos,a[i].x,a[i].y)) ans++;
			}
			lst=i+1;
		}
	}
	cout<<ans<<endl;
	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 <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
using namespace std;
typedef long long LL;
LL modu=(1LL<<31)-1;
LL modu2=(1LL<<62)-1;
pair<LL,LL> mult(LL a,LL b){
    if(a==0||b==0){
        return make_pair(0,0);
    }
    int sgn=1;
    if(a<0) sgn*=-1,a=-a;
    if(b<0) sgn*=-1,b=-b;
    LL a1=a>>31,a2=a&modu;
    LL b1=b>>31,b2=b&modu;
    LL c2=a2*b2;
    LL c1=a1*b1;
    LL tmp=a1*b2+a2*b1;
    c2+=(tmp&modu)<<31;
    c1+=tmp>>31;
    if(c2&1<<62L) c2^=1<<62L,c1++;
    c1*=sgn;
    c2*=sgn;
    return make_pair(c1,c2);
}
bool cmp(pair<LL,LL> a,pair<LL,LL> b){
    if(a.first==b.first){
        return a.second<b.second;
    }
    return a.first<b.first;
}
LL x[2000],y[2000],_x[2000],_y[2000];
bool exs[2000];
vector<pair<LL,LL>> K;
vector<LL> dst;
int main(){
    int n,i,j;
    scanf("%d",&n);
    LL cx=0,cy=0;
    for(i=0;i<n;i++){
        scanf("%lld%lld",x+i,y+i);
        cx+=x[i],cy+=y[i];
        _x[i]=x[i],_y[i]=y[i];
        x[i]*=n,y[i]*=n;
    }
    for(i=0;i<n;i++){
        x[i]-=cx,y[i]-=cy;
        exs[i]=x[i]||y[i];
    }
    for(i=0;i<n;i++){
        if(!exs[i]) continue;
        for(j=i+1;j<n;j++){
            if(!exs[j]) continue;
            if(x[i]==-x[j]&&y[i]==-y[j]){
                exs[i]=exs[j]=0;
                break;
            }
        }
    }
    for(i=0,j=0;i<n;i++){
        if(exs[i]){
            x[j]=x[i];
            y[j]=y[i];
            _x[j]=_x[i];
            _y[j]=_y[i];
            j++;
        }
    }
    n=j;
    if(n==0){
        printf("-1\n");
        return 0;
    }
    LL m2x,m2y,ex,ey,dc2;
    pair<LL,LL> dc;
    bool suc;
    K.clear();
    for(i=0;i<n;i++){
        m2x=x[0]+x[i];
        m2y=y[0]+y[i];
        ey=-m2x;
        ex=m2y;
        dst.clear();
        for(j=0;j<n;j++){
            dst.push_back(_x[j]*ex+_y[j]*ey);
        }
        sort(dst.begin(),dst.end());
        dc2=dst.front()+dst.back();
        suc=true;
        for(j=0;j<=(n-1)/2;j++){
            if(dst[j]+dst[n-1-j]!=dc2){
                suc=false;
                break;
            }
        }
        if(suc){
            K.push_back(make_pair(ey,ex));
        }
    }
    for(i=0;i<K.size();i++) exs[i]=1;
    for(i=0;i<K.size();i++){
        for(j=i+1;j<K.size();j++){
            if(mult(K[i].first,K[j].second)==mult(K[i].second,K[j].first)){
                exs[j]=0;
            }
        }
    }
    int cnt=0;
    for(i=0;i<K.size();i++){
        cnt+=exs[i];
    }
    printf("%d\n",cnt);
    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<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define N 2012
#define LL long long
int n,rt=0,ans=0,cn;LL b[N];bool vi[N];
struct Po{
	LL x,y;
	inline Po operator+(const Po &b)const{return (Po){x+b.x,y+b.y};}
	inline Po operator-(const Po &b)const{return (Po){x-b.x,y-b.y};}
	inline Po operator/(const int &b)const{return (Po){x/b,y/b};}
	inline bool operator==(const Po &b)const{return (x==b.x)&&(y==b.y);}
	inline LL operator*(const Po &b)const{return (x*b.y-y*b.x);}
	inline Po re(){return ((x<0)||((x==0)&&(y<0)))?((Po){-x,-y}):(*this);}
}a[N],c[N],co;
inline bool cmp(Po x,Po y){return ((x*y)>0);}
inline bool can(Po x){int i;for(i=1;i<=n;i++)b[i]=(x-a[i])*(co-a[i]);sort(b+1,b+n+1);for(i=1;i<=n;i++)if((b[i]+b[n-i+1])!=0)return false;return true;}
int main(){
	scanf("%d",&n);int i,j;for(i=1;i<=n;i++)scanf("%lld%lld",&a[i].x,&a[i].y),a[i].x*=(n<<1),a[i].y*=(n<<1),co=co+a[i];co=co/n;
	for(i=1;i<=n;i++)
	for(j=i;j<=n;j++)if(((a[i]+a[j])/2)==co)vi[i]=vi[j]=1;
	for(i=1;i<=n;i++)if(!vi[i])rt=i;if(!rt){printf("-1");return 0;}
	for(i=1;i<=n;i++)if(can((a[rt]+a[i])/2))c[++cn]=(co-((a[rt]+a[i])/2)).re();
	sort(c+1,c+cn+1,cmp);ans=(cn>0);for(i=2;i<=cn;i++)ans+=(c[i-1]*c[i])!=0;printf("%d",ans);return 0;
}

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

const int N = 2020;
const double eps = 1e-12;

int fcmp(double x) {
  return fabs(x) > eps ? (x < 0 ? -1 : 1) : 0;
}

struct Point {
  double x, y;

  Point Conj(void) {
    return (Point){-y, x};
  }

  double operator ^ (const Point &rhs) const {
    return x * rhs.y - y * rhs.x;
  }

  double operator * (const Point &rhs) const {
    return x * rhs.x + y * rhs.y;
  }

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

  Point operator - (const Point &rhs) const {
    return (Point){x - rhs.x, y - rhs.y};
  }

  Point operator / (const double &rhs) const {
    return (Point){x / rhs, y / rhs};
  }

  double Len(void) const {
    return x * x + y * y;
  }
}p[N], Grv;

struct Info {
  Point p;
  int u, v;
  double slope;

  bool operator < (const Info &rhs) const {
    return fcmp(slope - rhs.slope) < 0;
  }
};

int n, vis[N];

int main(void) {
  scanf("%d", &n);
  for(int i = 1; i <= n; i++) {
    scanf("%lf%lf", &p[i].x, &p[i].y);
    Grv = Grv + p[i];
  }
  Grv = Grv / n;
  //cerr << Grv.x << " " << Grv.y << endl;
  for(int i = 1; i < n; i++) {
    for(int j = i + 1; j <= n; j++) {
      if(!fcmp((p[j] - Grv).Len() - (p[i] - Grv).Len()) &&
	 !fcmp((p[j] - Grv) ^ (p[i] - Grv))) {
	vis[i] = 1;
	vis[j] = 1;
      }
    }
  }
  int m = 0;
  for(int i = 1; i <= n; i++) {
    if(vis[i]) continue;
    p[++m] = p[i];
  }
  n = m;
  if(n <= 2) {
    puts("-1");
    return 0;
  }

  Point now;
  vector<Info> E;
  int Ans = 0;
  for(int i = 1; i < n; i++) {
    for(int j = i + 1; j <= n; j++) {
      now = (Point){2 * Grv.y - p[i].y - p[j].y, p[i].x + p[j].x - 2 * Grv.x};
      if(fcmp(now.y) < 0) {
	now.x = -now.x;
	now.y = -now.y;
      }
      if(!fcmp(now.y) && fcmp(now.x) > 0) {
	now.x = -now.x;
      }
      E.push_back((Info){now, i, j, atan2(now.y, now.x)});
      //cerr << E.back().slope << endl;
    }
  }
  sort(E.begin(), E.end());

  //cerr << E.size() << endl;
  for(int i = 0; i < E.size(); i++) {
    int j = i;
    while(j + 1 < E.size() && !fcmp(E[j + 1].p ^ E[i].p)) {
      j++;
    }
    if(j - i + 1 >= n / 2) {
      for(int k = 1; k <= n; k++) {
	vis[k] = 0;
      }
      for(int k = i; k <= j; k++) {
	if(vis[E[k].u] || vis[E[k].v]) {
	  continue;
	}
	vis[E[k].u] = 1;
	vis[E[k].v] = 1;
      }
      int cnt = 0, id;
      for(int k = 1; k <= n; k++) {
	if(!vis[k]) {
	  cnt++;
	  id = k;
	}
      }
      if(cnt > 1 && (n & 1) || cnt && (~n & 1)) {
	continue;
      }
      //cerr << i << " " << j << " " << cnt << endl;
      if(!cnt || !fcmp(E[i].p * (p[id] - Grv))) {
	Ans++;
      }
    }
    i = j;
  }
  cout << Ans << endl;
  return 0;
}

#include<bits/stdc++.h>
using namespace std;
const int N=2005;
typedef long long ll;
struct point {
	double x,y;
} p[N],mid,line;
point operator + (point s, point t) {
	return (point){s.x+t.x,s.y+t.y};
}
int n,del[N];
pair<double,int> x[N];
bool eq(double x, double y) { return fabs(x-y)<1e-9; }
bool check1(int a, int b) { return eq(mid.x-p[a].x,p[b].x-mid.x)&&eq(mid.y-p[a].y,p[b].y-mid.y); }
double mult(double x1, double y1, double x2, double y2) { return x1*x2+y1*y2; }
bool check(int a)
{
	line=(point){mid.y-(p[1].y+p[a].y)/2.0,(p[1].x+p[a].x)/2.0-mid.x};
	for(int i=1;i<=n;++i) x[i]=make_pair(mult(line.x,line.y,p[i].x,p[i].y),i);
	sort(x+1,x+1+n);
	int x1=0,x2=0;
	for(int i=1;i<=n;++i)
	{
		if(x[i].second==1) x1=i;
		if(x[i].second==a) x2=i;
	}
	if(x1+x2!=n+1) return false;
	for(int i=2;i<=n;++i) if(!eq(x[1].first+x[n].first,x[i].first+x[n-i+1].first)) return false;
	return true;
}
int main()
{
	scanf("%d",&n);
	mid=(point){0,0},memset(del,false,sizeof(del));
	for(int i=1;i<=n;++i) scanf("%lf%lf",&p[i].x,&p[i].y),mid=mid+p[i];
	mid.x/=n,mid.y/=n;
	for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j)
		if(check1(i,j)) del[i]=del[j]=true;
	int cnt=0,ans=0;
	for(int i=1;i<=n;++i) if(!del[i]) p[++cnt]=p[i];
	n=cnt;
	if(n<=2) {
		puts("-1");
		return 0;
	}
	for(int i=1;i<=n;++i) ans+=check(i);
	printf("%d\n",ans);
}

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

#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define lg long long
#define db double
#define lb(x) ((x)&-(x))
#define ft first
#define sd second

#define HII cerr<<"HI"<<endl
#define LLLINE cerr<<"@@@@@@@@@@@@@@@@@@@@"<<endl

template <class _T_>
void read(_T_& d){
	d=0;int f=1;char c=getchar();
	for(;c<'0'||c>'9';c=getchar())if(c=='-')f*=-1;
	for(;c>='0'&&c<='9';c=getchar())d=d*10+c-'0';
	d*=f;
}

/************************************************/
#define MN 2205
const double eps=1e-9;
struct Node{
	db x,y;
}p[MN],rt,P;
Node operator+(Node A,Node B){
	return (Node){A.x+B.x,A.y+B.y};
}
Node operator-(Node A,Node B){
	return (Node){A.x-B.x,A.y-B.y};
}
Node operator*(Node A,db B){
	return (Node){A.x*B,A.y*B};
}
Node operator/(Node A,db B){
	return (Node){A.x/B,A.y/B};
}
db operator*(Node A,Node B){
	return A.x*B.x+A.y*B.y;
}
bool operator==(Node A,Node B){
	return A.x==B.x&&A.y==B.y;
}

int res,n,a;
pair<db,int> PP[MN];

bool Doit(int x){
	P=(p[a]+p[x])*.5;
	Node var=rt-P;
	var=(Node){var.y,-var.x};
	for(int i=1;i<=n;++i){
		PP[i]=mp(var*p[i],i);
	}
	sort(PP+1,PP+n+1);
	int G=0;
	for(int i=1;i<=n;++i){
		if(PP[i].sd==x)G+=i;if(PP[i].sd==a)G+=i;
	}
	if(G!=n+1)return 0;
	for(int i=1;i<=n;++i){
		if(abs(PP[i].ft+PP[n-i+1].ft-PP[1].ft-PP[n].ft)>eps)return 0;
	}
	return 1;
}

int main(){
//	int _T;
//	read(_T);
//	while(_T--){
		read(n);res=0;
		//if(n<0){puts("-1");continue;}
		for(int i=1;i<=n;++i){
			scanf("%lf%lf",&p[i].x,&p[i].y);rt=rt+p[i];
		}
		rt=rt/n;
		for(int i=1;i<=n;++i){
			int A=1;
			for(int j=1;j<=n;++j)if(p[i]+p[j]==rt+rt)A=0;
			if(A){a=i;goto Turtle;}
		}
		return puts("-1"),0;
Turtle:
		for(int i=1;i<=n;++i)if(Doit(i))++res;
		printf("%d\n",res);
	//}
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
inline int cmp(double a,double b)
{
	return fabs(a-b)<1e-7?0:(a-b>0)?1:-1;
}
class vec
{
	public:
		double x,y;
		vec(){}
		vec(double tx,double ty){x=tx,y=ty;}
		vec operator +(const vec &t){return vec(x+t.x,y+t.y);}
		vec operator -(const vec &t){return vec(x-t.x,y-t.y);}
		double operator *(const vec &t){return x*t.x+y*t.y;}
		vec operator *(const double &t){return vec(x*t,y*t);}
		vec operator /(const double &t){return vec(x/t,y/t);}
		bool operator ==(const vec &t){return cmp(x,t.x)==0&&cmp(y,t.y)==0;}
		double len(){return sqrt(x*x+y*y);}
		vec sing(){return *this/len();}
}v[2010];
int n,bcnt=0;
vec cet;
bool ban[2010];
double val[2010];
vector<vec> v2;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lf%lf",&v[i].x,&v[i].y),cet=cet+v[i];
	cet=cet/n;
	for(int i=1;i<=n;i++)
	{
		if(v[i]==cet)
		{
			ban[i]=1;
			bcnt++;
			continue;
		}
		if(!ban[i])
		for(int j=i+1;j<=n;j++)
		{
			if(ban[j])continue;
			if(v[i]+v[j]==cet*2)
			{
				ban[i]=ban[j]=1;
				bcnt+=2;
				break;
			}
		}
	}
	for(int i=1;i<=n;i++)
		if(!ban[i])v2.push_back(v[i]);
	if(!v2.size())
	{
		puts("-1");
		return 0;
	}
	vector<vec> lans;
	int ans=0;
	for(int i=0;i<v2.size();i++)
	{
		vec mid=(v2[0]+v2[i])/2;
		vec l1=cet-mid;
		vec l2=vec(-l1.y,l1.x).sing();
		for(int j=0;j<v2.size();j++)
			val[j]=v2[j]*l2;
		sort(val,val+v2.size());
		double vc=cet*l2;
		bool flag=1;
		for(int j=0;j<lans.size();j++)
		{
			if(l2==lans[j]||l2==lans[j]*(-1))
			{
				flag=0;
				break;
			}
		}
		if(!flag)continue;
		lans.push_back(l2);
		for(int l=0,r=v2.size()-1;l<=r;l++,r--)
		{
			if(cmp(val[l]+val[r],vc*2))
			{
				flag=0;
				break;
			}
		}
		ans+=flag;
	}
	printf("%d\n",ans);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge {c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

typedef long long ll;
struct P {
	ll x, y;
	void read() {
		scanf("%lld%lld", &x, &y);
	}
	P operator - (const P & he) const {
		return P{x - he.x, y - he.y};
	}
	P operator + (const P & he) const {
		return P{x + he.x, y + he.y};
	}
	P operator * (ll mul) const {
		return P{x * mul, y * mul};
	}
	P operator / (ll mul) const {
		assert(x % mul == 0 && y % mul == 0);
		return P{x / mul, y / mul};
	}
	ll operator *(const P & he) const {
		return x * he.y - y * he.x;
	}
	bool operator == (const P & he) const {
		return x == he.x && y == he.y;
	}
};

int main() {
	int n;
	scanf("%d", &n);
	vector<P> points(n);
	P mid = {0, 0};
	for(P & p : points) {
		p.read();
		p = p * 2;
		mid = mid + p;
		p = p * n;
	}
	debug() << imie(mid.x) imie(mid.y);
	vector<bool> vis(n);
	for(int i = 0; i < (int) points.size(); ++i)
		if(!vis[i]) {
			if(points[i] == mid) {
				vis[i] = true;
				continue;
			}
			for(int j = i + 1; j < (int) points.size(); ++j)
				if(!vis[j] && (points[i] - mid) == (mid - points[j])) {
					vis[i] = vis[j] = true;
					break;
				}
		}
	vector<P> nowe;
	for(int i = 0; i < n; ++i)
		if(!vis[i])
			nowe.push_back(points[i]);
	points = nowe;
	n = points.size();
	debug() << imie(n);
	if(n <= 1) {
		puts("-1");
		return 0;
	}
	int answer = 0;
	vector<P> already;
	for(int i = 0; i < n; ++i) {
		P he = (points[0] + points[i]) / 2;
		debug() << imie(i) imie(he.x) imie(he.y);
		assert(!(he == mid));
		bool ok = true;
		for(const P & p : already) if((p - mid) * (he - mid) == 0) {
			ok = false;
			break;
		}
		if(!ok) continue;
		vector<ll> values;
		for(const P & p : points)
			values.push_back((p - mid) * (he - mid));
		sort(values.begin(), values.end());
		ll should = values[0] + values.back();
		for(int j = 0; j < n; ++j)
			if(values[j] + values[n-1-j] != should) {
				ok = false;
				break;
			}
		if(ok) {
			++answer;
			already.push_back(he);
		}
	}
	printf("%d\n", answer);
}

#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <bits/stdc++.h>
/*#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")*/

using namespace __gnu_pbds;
using namespace std;

#define ll long long
#define ld long double
#define mp make_pair
#define what_is(x) cerr << #x << " is " << x << endl;

typedef tree<
        int,
        null_type,
        less<int>,
        rb_tree_tag,
        tree_order_statistics_node_update>
        ordered_set;

const int p = 1e9 + 7;

int mul(int a, int b) {
    return (1LL * a * b) % p;
}

int add(int a, int b) {
    int s = (a+b);
    if (s>=p) s-=p;
    return s;
}

int sub(int a, int b) {
    int s = (a+p-b);
    if (s>=p) s-=p;
    return s;
}

int po(int a, int deg)
{
    if (deg==0) return 1;
    if (deg%2==1) return mul(a, po(a, deg-1));
    int t = po(a, deg/2);
    return mul(t, t);
}

int inv(int n)
{
    return po(n, p-2);
}

vector<int> Z(vector<int> s)
{
    int n = s.size();
    vector<int> z(n);
    int L = 0, R = 0;
    for (int i = 1; i < n; i++) {
        if (i > R) {
            L = R = i;
            while (R < n && s[R-L] == s[R]) R++;
            z[i] = R-L; R--;
        } else {
            int k = i-L;
            if (z[k] < R-i+1) z[i] = z[k];
            else {
                L = i;
                while (R < n && s[R-L] == s[R]) R++;
                z[i] = R-L; R--;
            }
        }
    }
    return z;
}

mt19937 rnd(time(0));
/*
struct Line {
    mutable ll k, m, p;
    bool operator<(const Line& o) const { return k < o.k; }
    bool operator<(ll x) const { return p < x; }
};

struct CHT : multiset<Line, less<>> {
    // (for doubles, use inf = 1/.0, div(a,b) = a/b)
    const ll inf = LLONG_MAX;
    ll div(ll a, ll b) { // floored division
        return a / b - ((a ^ b) < 0 && a % b); }
    bool isect(iterator x, iterator y) {
        if (y == end()) { x->p = inf; return false; }
        if (x->k == y->k) x->p = x->m > y->m ? inf : -inf;
        else x->p = div(y->m - x->m, x->k - y->k);
        return x->p >= y->p;
    }
    void add(ll k, ll m) {
        auto z = insert({k, m, 0}), y = z++, x = y;
        while (isect(y, z)) z = erase(z);
        if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
        while ((y = x) != begin() && (--x)->p >= y->p)
            isect(x, erase(y));
    }
    ll query(ll x) {
        assert(!empty());
        auto l = *lower_bound(x);
        return l.k * x + l.m;
    }
};
*/

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

    int n;
    cin>>n;
    vector<ll> x(n);
    vector<ll> y(n);
    for (int i = 0; i<n; i++)
    {
        cin>>x[i]>>y[i];
        x[i]*=(2*n);
        y[i]*=(2*n);
    }
    ll totalx = 0;
    ll totaly = 0;
    for (int i = 0; i<n; i++)
    {
        totalx+=x[i];
        totaly+=y[i];
    }
    totalx/=n;
    totaly/=n;

    for (int i = 0; i<n; i++)
    {
        x[i]-=totalx;
        y[i]-=totaly;
    }

    //for (int i = 0; i<n; i++) cout<<x[i]<<' '<<y[i]<<endl;

    set<pair<ll, ll>> pt;
    for (int i = 0; i<n; i++) pt.insert(mp(x[i], y[i]));
    if (pt.find(mp(0, 0))!=pt.end()) pt.erase(mp(0, 0));
    while (true)
    {
        pair<int, int> kek;
        bool found = false;
        for (auto it: pt) if (pt.find(mp(-it.first, -it.second))!=pt.end())
            {
                kek = it;
                found = true;
                break;
            }
        if (found)
        {
            pt.erase(kek);
            pt.erase(mp(-kek.first, -kek.second));
            continue;
        }
        break;
    }

    vector<pair<ll, ll>> guys;
    for (auto it: pt) guys.push_back(it);
    if (guys.size()==0) {cout<<-1; return 0;}

    set<pair<ll, ll>> lines;

    n = guys.size();

    int counter = 0;

    for (int i = 0; i<n; i++)
    {
        ll x1 = (guys[0].first + guys[i].first)/2;
        ll y1 = (guys[0].second + guys[i].second)/2;
        if (x1<0) {x1*=-1; y1*=-1;}
        ll t = __gcd(abs(x1), abs(y1));
        x1/=t;
        y1/=t;
        if (lines.find(mp(x1, y1))!=lines.end()) continue;
        lines.insert(mp(x1, y1));
        x1 = (guys[0].first + guys[i].first)/2;
        y1 = (guys[0].second + guys[i].second)/2;
        vector<ll> kek;
        for (int j = 0; j<n; j++)
        {
            kek.push_back(guys[j].first*y1 - guys[j].second*x1);
        }
        sort(kek.begin(), kek.end());
        /*cout<<i<<": "<<endl;
        for (auto it: kek) cout<<it<<' ';
        cout<<endl;*/
        bool check = true;
        for (int j = 0; j<n; j++) if (kek[j]!=-kek[n-1-j]) check = false;
        if (check) counter++;
    }
    cout<<counter;

}

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <string>
#include <stack>
#include <set>
#include <cassert>
#include <ctime>
#include <unordered_set>
#include <complex>
#include <queue>

#define vd vector<double>
#define pb push_back
#define all(v) v.begin(), v.end()
#define x first
#define y second
#define mp make_pair
#define forn(i, l) for (int i = 0; i < l; i++)

using namespace std;
typedef pair<int, int> pi;
typedef long double ld;
typedef pair<ld, ld> pd;
typedef long long li;
const int N = 2e3 + 10;
const ld eps = 0.2, eps2 = 0.0001;
const int INF = (int)1e9 + 2;
const long long LINF = 1e16;
const double PI = acos(-1.0);

int n;
pi mas[N];
li temp[N];
char used[N];
ld cx, cy;
long long Cx, Cy;

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

int main() {
#ifdef _DEBUG
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	scanf("%d", &n);
	forn(i, n) {
		scanf("%d%d", &mas[i].x, &mas[i].y);
		cx += mas[i].x;
		Cx += mas[i].x;
		cy += mas[i].y;
		Cy += mas[i].y;
	}
	cx /= n;
	cy /= n;
	int r = n;
	forn(i, n) {
		if (used[i]) {
			continue;
		}
		if ((n * 1LL * mas[i].x - Cx) == 0 && (n * 1LL * mas[i].y - Cy) == 0) {
			used[i] = 1;
			mas[i].x = mas[i].y = INF;
			r--;
			continue;
		}
		forn(j, i) {
			if (Cx * 2 - n * 1LL * (mas[i].x + mas[j].x) == 0 && Cy * 2 - n * 1LL * (mas[i].y + mas[j].y) == 0) {
				used[i] = used[j] = 1;
				mas[i].x = mas[i].y = INF;
				mas[j].x = mas[j].y = INF;
				r -= 2;
				break;
			}
		}
	}
	sort(mas, mas + n);
	if (r < 1) {
		printf("-1");
		return 0;
	}
	vector<pair<li, li> > ans;
	int sz = 0;
	forn(i, r) {
		li x2 = (mas[0].x + mas[i].x);
		li y2 = (mas[0].y + mas[i].y);
		ld a = Cx * 2 - x2 * n, b = Cy * 2 - y2 * n;
		forn(j, r) {
			li del = - b * mas[j].x + a * mas[j].y;
			temp[j] = del;
		}
		x2 = temp[0] + temp[i];
		sort(temp, temp + r);
		//forn(j, r) {
		//	cout << '(' << temp[j].x << ',' << temp[j].y << ')' << endl;
		//}
		bool ok = 1;
		ld er = 0;
		forn(j, r) {
			//if (abs(2 * x2 - temp[j].x - temp[r - 1 - j].x) >= eps || abs(2 * y2 - temp[j].y - temp[r - 1 - j].y) >= eps) {
			//	ok = 0;
			//	break;
			//}
			li t = x2 - temp[j] - temp[r - 1 - j];
			if (t != 0) {
				ok = 0;
				break;
			}
		}
			//cout << er << "______________--" << '(' <<x2 << ',' << y2 << ')'<< endl;
		if (ok) {
			li A = 2 * Cx - n * 1LL * (mas[0].x + mas[i].x);
			li B = 2 * Cy - n * 1LL * (mas[0].y + mas[i].y);
			if (A < 0) {
				A /= -1;
				B /= -1;
			}
			long long d = gcd(A, B);
			ans.pb(mp(A / d, B / d));
		}
	}
	if (ans.empty()) {
		printf("0");
		return 0;
	}
	sort(all(ans));
	forn(i, ((int)ans.size()) - 1) {
		if ((ans[i].x == ans[i + 1].x) && (ans[i].y == ans[i + 1].y)) {
			sz++;
		}
	}
	printf("%d", ans.size() - sz);
	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 int long long
#define x first
#define y second
#define ilo( a, b ) ( a.x*b.y-b.x*a.y )

list<pair<int, int> > v;
int n;
pair<int, int> sr;

void usun() {
    for( auto it = v.begin(); it != v.end(); it++ ) {
        for( auto it2 = it; it2 != v.end(); it2++ ) {
            //if( it == it2 ) continue;
            if( (it->x+it2->x)*n == 2*sr.x && (it->y+it2->y)*n == 2*sr.y ) {
                if( it != it2 ) v.erase( it2 );
                it = v.erase( it );
                it--;
                break;
            }
        }
    }
}

pair<int, int> kier;
int odl[2200];
bool spr() {
    int li=0;
    for( pair<int, int> i : v ) {
        i.x*=n;
        i.y*=n;
        odl[li] = ilo( kier, i );
        li++;
    }
    odl[v.size()] = ilo( kier, sr );
    sort( odl, odl+v.size()+1 );
    if( v.size()%2 ) {
        if( odl[(v.size()+1)/2] != ilo( kier, sr ) ) {
            return 0;
        }
        swap( odl[(v.size()+1)/2], odl[v.size()] );
        sort( odl, odl+v.size() );
    }

    if( odl[v.size()/2] != ilo( kier, sr ) ) return 0;
    for( int pocz, kon=pocz=v.size()/2; pocz>0; pocz--, kon++ ) {
        if( odl[pocz]-odl[pocz-1] != odl[kon+1]-odl[kon] ) return 0;
    }
    return 1;
}

set<pair<int, int> > used;

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

    cin >> n;
    for( int a, b, i=1; i<=n; i++ ) {
        cin >> a >> b;
        v.push_back( {a*2, b*2} );
        sr.x += a*2;
        sr.y += b*2;
    }

    usun();
    if( v.size() == 0 ) {
        cout << -1;
        return 0;
    }
    if( v.size() == 1 && v.front().x*n == sr.x && v.front().y == sr.y ) {//jesli jest jeden na srodku
        cout << -1;
        return 0;
    }

    int res = 0;
    pair<int, int> pom;
    for( auto i : v ) {
        //if( i == v.front() ) continue;
        pom.x = (v.front().x+i.x)/2*n;
        pom.y = (v.front().y+i.y)/2*n;
        kier.x = pom.x-sr.x;
        kier.y = pom.y-sr.y;
        int nwd = __gcd( kier.x, kier.y );
        kier.x /= nwd;
        kier.y /= nwd;
        if( kier.x < 0 ) {
            kier.x = -kier.x;
            kier.y = -kier.y;
        } else if( kier.x == 0 && kier.y < 0 ) {
            kier.x = -kier.x;
            kier.y = -kier.y;
        }
        if( used.find( kier ) == used.end() ) {
            res += spr();
            used.insert( kier );
        }
    }
    cout << res;

    return 0;
}

#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 namespace std;

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

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

const int N = 2'000;

long long dist[N];
point points[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 * n, y * n);
    center += point(x, y);
  }

  for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
      if (!dead[i] && !dead[j]) {
        point u = 2LL * center - points[i] - points[j];
        if (u.X == 0 && u.Y == 0) {
          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 = 2LL * center - points[i] - points[pivot];

      bool ok = true;
      for (auto j : angles) {
        ok &= (cross(vec, j) != 0);
      }

      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 &= (dist[i] + dist[n - 1 - i] - 2 * cross(vec, center) == 0);
      }

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

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

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define pii pair<int,int>
#define pll pair<ll,ll>
#define PB push_back
#define MP make_pair

vector< pll > v;
ll n, xc = 0, yc = 0;

void PreProcess(){
  map< pll, int > M;

  for(auto p : v){
    ll x, y;
    tie(x, y) = p;
    x -= xc, y -= yc;

    if(x == 0 && y == 0)
      continue;

    pll q = MP(-x, -y);
    if(M[q] > 0)
      --M[q];
    else
      ++M[MP(x, y)];
  }

  v.clear();

  for(auto it : M){
    auto p = it.first;
    int x = it.second;
    while(x--)
      v.PB(p);
  }
}

int main(){
  scanf("%lld", &n);
  for(int i = 1; i <= n; ++i){
    ll x, y;
    scanf("%lld%lld", &x, &y);
    x *= 2 * n, y *= 2 * n;
    v.PB(MP(x, y));
    xc += (x / n), yc += (y / n);
  }

  PreProcess();

  n = v.size();

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

  int ans = 0;
  ll x1, y1;

  tie(x1, y1) = v.back();

  set< pll > S;

  for(int i = 0; i < n; ++i){
    ll x2, y2, a, b;
    map< ll, int > M;

    tie(x2, y2) = v[i];

    b = - (x1 + x2) / 2, a = (y1 + y2) / 2;

    if(a < 0)
      b *= -1, a *= -1;

    if(a == 0)
      b = abs(b);

    ll g = __gcd(abs(a), abs(b));
    a /= g, b /= g;

    if(S.find(MP(b, a)) != S.end())
      continue;

    S.insert(MP(b, a));

    for(auto q : v){
      ll x, y;

      tie(x, y) = q;
      ll z = a * x + b * y;

      if(z == 0)
        continue;

      if(M[-z] > 0)
        --M[-z];
      else
        ++M[z];
    }

    bool valid = 1;

    for(auto it : M)
      valid &= (it.second == 0);

    ans += valid;
    S.insert(v[i]);
  }

  printf("%d\n", ans);

  return 0;
}

#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <cstdio>
#include <cstring>
#include <string>
#include <string.h>
#include <cmath>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <set>
#include <vector>
#include <map>
#include <iomanip>
#include <stdlib.h>
#include <queue>
#include <list>
#include <stack>
#include <bitset>
#include <fstream>
#include <sstream>
#include <random>
#include <assert.h>
#include <unordered_map>
#define eps 1e-7
#define SIZE 2010
#define rep(i, a, b) for (long long i = a; i <= b; ++i)
#define pi acos(-1.0)
#define mp make_pair
#define int long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
int n, cnt, m, ans;
bool vis[SIZE], vs[SIZE];
int __gcd(int a, int b) {
	return b == 0 ? a : __gcd(b, a % b);
}
struct Point {
	int x, y;
	Point() {}
	Point(int xx, int yy) :x(xx), y(yy) {}
	void input() { scanf("%lld %lld", &x, &y); }
}p[SIZE], G, tp[SIZE];
struct Node {
	int x, y;
	int i, j;
	Node() {}
	Node(int x_, int y_, int i_, int j_) :x(x_), y(y_), i(i_), j(j_) {}
	bool operator <(const Node& b) {
		return x < b.x || (x == b.x && y < b.y);
	}
	bool operator ==(const Node& b) {
		return x == b.x && y == b.y;
	}
};
Point operator +(Point a, Point b) { return Point(a.x + b.x, a.y + b.y); }	//向量加法
Point operator -(Point a, Point b) { return Point(a.x - b.x, a.y - b.y); }	//向量减法
Point operator *(Point a, int t) { return Point(a.x * t, a.y * t); }	//向量数乘
Point operator / (Point a, int p) { return Point(a.x / p, a.y / p); }	//向量数乘的除法形式
bool operator ==(Point a, Point b) { return (a.x == b.x && a.y == b.y); }
bool operator <(Point a, Point b) { return (a.x < b.x) || (a.x == b.x && a.y < b.y); }
vector<Node> v;
signed main() {
	G.x = 0, G.y = 0;
	io(); cin >> n;
	rep(i, 1, n) cin >> p[i].x >> p[i].y;
	rep(i, 1, n) p[i] = p[i] * (2 * n);
	rep(i, 1, n) G = G + p[i];
	G = G / n;
	rep(i, 1, n) if (G == p[i]) vis[i] = true;
	rep(i, 1, n) {
		if (vis[i]) continue;
		rep(j, (i + 1), n) {
			if (vis[j]) continue;
			if (G == (p[i] + p[j]) / 2) vis[i] = vis[j] = true;
		}
	}
	rep(i, 1, n) {
		if (vis[i]) continue;
		tp[++m] = p[i];
	}
	if (!m) { cout << "-1"; return 0; }
	if (m & 1) {
		rep(i, 1, m) {
			Point tmp = tp[i] - G;
			if (tmp.x < 0 || (!tmp.x && tmp.y < 0)) tmp.x = -tmp.x, tmp.y = -tmp.y;
			int g = __gcd(abs(tmp.x), abs(tmp.y));
			tmp = tmp / g;
			v.emplace_back(Node(tmp.x, tmp.y, i, i));
		}
	}
	rep(i, 1, m) {
		rep(j, (i + 1), m) {
			Point tmp = (tp[i] + tp[j]) / 2 - G;
			if (tmp.x < 0 || (!tmp.x && tmp.y < 0)) tmp.x = -tmp.x, tmp.y = -tmp.y;
			int g = __gcd(abs(tmp.x), abs(tmp.y));
			tmp = tmp / g;
			v.emplace_back(Node(tmp.x, tmp.y, i, j));
		}
	}
	sort(v.begin(), v.end());
	Node now = *v.begin();
	int pre = 0;
	rep(i, 0, (v.size() - 1)) {
		if (v[i] == now) {
			++cnt;
			if (i != (v.size() - 1)) continue;
			++i;
			if ((cnt << 1) < m) break;
			else {
				for (int j = i; cnt; --cnt) {
					int lc = j - cnt;
					vs[v[lc].i] = vs[v[lc].j] = true;
				}
			}
			rep(j, 1, m) if (!vs[j]) break;
			++ans;
			break;
			//vs[it.i] = vs[it.j] = true;
		}
		if ((cnt << 1) < m) {
			pre = i;
			now = v[i];
			cnt = 1;
			continue;
		}
		else {
			for (int j = i; cnt; --cnt) {
				int lc = j - cnt;
				vs[v[lc].i] = vs[v[lc].j] = true;
			}
		}
		rep(j, 1, m) {
			if (vs[j]) {
				vs[j] = false;
				++cnt;
			}
		}
		if (cnt == m) ++ans;
		cnt = 1;
		pre = i;
		now = v[i];
	}
	cout << ans;
}

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 2050;
const double eps = 1e-8,inf = 1e10;
int n,m,ans,vis[maxn];
struct point{
	double x,y;
	point operator + (point p){
		return {x + p.x,y + p.y};
	}
	point operator - (point p){
		return {x - p.x,y - p.y};
	}
	point operator * (double a){
		return {x * a,y * a};
	}
	point operator / (double a){
		return {x / a,y / a};
	}
	double operator * (point p){
		return x * p.x + y * p.y;
	}
	bool operator == (point p){
		if(fabs(x - p.x) < eps && fabs(y - p.y) < eps) return 1;
		else return 0;
	}
}g,t[maxn],p[maxn];
struct node{
	double k;
	int a,b;
	bool operator < (node p){
		return k < p.k;
	}
}q[maxn * maxn];
int read(){
	int x = 0,f = 1;
	char c = getchar();
	while(c < '0' || c > '9'){
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
	return x * f;
}
int main(){
	n = read();
	for(int i = 1; i <= n; i ++) t[i] = {read(),read()},g = g + t[i];
	// if(n == 2000 && t[1] == (point){1000000,999999}){cout << 1 << endl;return 0;}
	g = g / n;
	for(int i = 1; i <= n; i ++){
		for(int j = i; j <= n; j ++){
			if(t[i] + t[j] == g * 2){
				vis[i] = 1,vis[j] = 1;
				break;
			}
		}
	}
	for(int i = 1; i <= n; i ++) if(!vis[i]) p[++m] = t[i] - g;
	if(m <= 1){
		printf("-1\n");
		return 0;
	}
	n = 0;
	for(int i = 1; i <= m; i ++)
		for(int j = i + 1; j <= m; j ++)
			q[++n] = {fabs(p[i].y + p[j].y) < eps ? inf : -(p[i].x + p[j].x) / (p[i].y + p[j].y),i,j};
	sort(q + 1,q + n + 1);
	int last = 1;
	for(int i = 1; i <= n; i ++){
		if(i != n && q[i + 1].k - q[i].k < eps) continue;
		if(i - last + 1 >= m / 2){
			for(int j = 1; j <= m; j ++) vis[j] = 0;
			for(int j = last; j <= i; j ++) if(!vis[q[j].a] && !vis[q[j].b]) vis[q[j].a] = vis[q[j].b] = 1;
			int cnt = 0,pos = 0;
			for(int j = 1; j <= m; j ++) if(!vis[j]) cnt ++,pos = j;
			if(cnt > m % 2){
				last = i + 1;
				continue;
			}
			if(!cnt || (fabs(inf - q[i].k) < eps ? fabs(p[pos].y) < eps : fabs(p[pos] * (point){1,q[i].k}) < eps)) ans ++;
		}
		last = i + 1;
	}
	printf("%d\n",ans);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge {c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

typedef long double ld;

struct P {
	ld x, y;
	int id;
	void read() {
		scanf("%Lf%Lf", &x, &y);
		//~ x *= 2;
		//~ y *= 2;
	}
	P operator - (const P & he) const {
		return P{x - he.x, y - he.y};
	}
	P operator + (const P & he) const {
		return P{x + he.x, y + he.y};
	}
	ld operator * (const P & he) const {
		return x * he.y - y * he.x;
	}
	bool operator < (const P & he) const {
		return *this * he < 0;
	}
	bool iszero() const {
		return max(abs(x), abs(y)) < 1e-8;
		//~ return x == 0 && y == 0;
	}
	bool operator == (const P & he) {
		return (*this - he).iszero();
		//~ return x == he.x && y == he.y;
	}
	P operator / (ld m) const {
		return P{x / m, y / m};
	}
	//~ ld dist(const P & he) const {

};

//~ bool collinear(vector<P> points) {
	//~ bool any_dir = false;
	//~ P dir;
	//~ for(int i = 1; i < (int) points.size(); ++i) {
		//~ P rel = points[i] - points[0];
		//~ if(rel.iszero()) continue;
		//~ if(!any_dir) {
			//~ any_dir = true;
			//~ dir = rel;
			//~ continue;
		//~ }
		//~ if(rel * dir) {
			//~ return false;
		//~ }
	//~ }
	//~ return true;
//~ }

int main() {
	int n;
	scanf("%d", &n);
	vector<P> points(n);
	P total{0, 0};
	for(P & p : points) {
		p.read();
		total.x += p.x / n;
		total.y += p.y / n;
		//~ p.x *= n;
		//~ p.y *= n;
	}

	if(n == 1) {
		puts("-1");
		return 0;
	}

	if(points[0] == total) swap(points[0], points[1]);

	vector<P> candidates;
	candidates.push_back(points[0]);
	for(int i = 1; i < n; ++i)
		candidates.push_back((points[0] + points[i]) / 2.);

	int answer = 0;
	vector<P> already;
	debug() << imie(total.x) imie(total.y);
	auto check = [&] (P cand) {
		debug() << imie(cand.x) imie(cand.y);
		if(cand == total) return;
		for(P p : already)
			if(abs((p - total) * (cand - total)) < 1e-9) {
				debug() << imie(p.x) imie(p.y) imie(cand.x) imie(cand.y);
				debug() << "skip";
				return;
			}
		already.push_back(cand);
		vector<ld> values;
		for(P p : points) {
			ld x = (p - total) * (cand - total);
			values.push_back(x);
		}
		sort(values.begin(), values.end());
		//~ debug() << imie(values);
		bool ok = true;
		ld should = values[0] + values.back();
		for(int i = 0; i <= (n + 1) / 2; ++i)
			if(abs(values[i] + values[n-1-i] - should) > 1e-11)
				ok = false;
		if(ok) ++answer;
	};

	check(P{rand() % 1000000 + 0.1234, rand() % 2913412 + 0.12352});
	if(answer) {
		puts("-1");
		return 0;
	}

	for(P c : candidates) check(c);
	//~ for(P he : candidates) {
	printf("%d\n", answer);
}

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

typedef double DB;
const DB PI = acos(DB(-1));
const DB INF = 1e10;
const DB EPS = 1e-8;

inline DB sqr(DB x) {
	return x * x;
}

struct PT {
	DB x, y;

	PT() {}
	PT(DB x, DB y) : x(x), y(y) {}
	void in() {
		scanf("%lf%lf", &x, &y);
	}
};

bool operator<(const PT& p1, const PT& p2) {
	if (fabs(p1.x - p2.x) > EPS) return p1.x < p2.x;
	return p1.y + EPS < p2.y;
}

bool operator==(const PT& p1, const PT& p2) {
	return fabs(p1.x - p2.x) < EPS && fabs(p1.y - p2.y) < EPS;
}

PT operator+(PT p1, PT p2) {
	return PT(p1.x + p2.x, p1.y + p2.y);
}

PT operator-(PT p1, PT p2) {
	return PT(p1.x - p2.x, p1.y - p2.y);
}

PT operator*(PT p, DB c) {
	return PT(p.x * c, p.y * c);
}

PT operator/(PT p, DB c) {
	return PT(p.x / c, p.y / c);
}

DB dis(PT p) {
	return sqrt(sqr(p.x) + sqr(p.y));
}

DB dis2(PT p) {
	return sqr(p.x) + sqr(p.y);
}

DB dis2(PT p1, PT p2) {
	return sqr(p1.x - p2.x) + sqr(p1.y - p2.y);
}

DB dis(PT p1, PT p2) {
	return sqrt(dis2(p1, p2));
}

DB vect(PT p1, PT p2) {
	return p1.x * p2.y - p2.x * p1.y;
}

DB scal(PT p1, PT p2) {
	return p1.x * p2.x + p1.y * p2.y;
}

DB getAngle(PT p) {
	return atan2(p.y, p.x);
}

DB vect(PT p, PT p1, PT p2) {
	return vect(p1 - p, p2 - p);
}

DB scal(PT p, PT p1, PT p2) {
	return scal(p1 - p, p2 - p);
}

DB getAngle(PT p, PT p1, PT p2) {
	return getAngle(p2 - p) - getAngle(p1 - p);
}

DB getAngle180(PT p, PT p1, PT p2) {
	return acos(scal(p, p1, p2) / dis(p, p1) / dis(p, p2));
}

DB disToLine(PT p, PT p1, PT p2) {
	return fabs(vect(p, p1, p2)) / dis(p1, p2);
}

DB disToSeg(PT p, PT p1, PT p2) {
	if (scal(p1, p, p2) < 0) return dis(p, p1);
	if (scal(p2, p, p1) < 0) return dis(p, p2);
	return disToLine(p, p1, p2);
}

bool onLine(PT p, PT p1, PT p2) {
	return fabs(vect(p1 - p, p2 - p)) < EPS;
}

bool onSeg(PT p, PT p1, PT p2) {
	if (!onLine(p, p1, p2)) return 0;
	return (p1.x - p.x) * (p2.x - p.x) < EPS && (p1.y - p.y) * (p2.y - p.y) < EPS;
}

PT projection(PT a, PT b, PT p) {
	return a + (a - b) * scal(p - a, a - b) / dis2(a - b);
}

int posLineLine(PT p1, PT p2, PT p3, PT p4, PT& p) {
	DB s1 = vect(p1, p2, p3), s2 = vect(p1, p2, p4);
	if (fabs(s1 - s2) < EPS) {
		if (fabs(s1) < EPS) return 2;
		return 0;
	}
	p = p3 + (p4 - p3) * s1 / (s1 - s2);
	return 1;
}

int posCirLine(PT p, DB r, PT p1, PT p2, PT *q) {
	DB a, b, c, d2, d;
	a = dis2(p1, p2);
	b = scal(p1, p, p2);
	c = dis2(p, p1) - sqr(r);
	d2 = sqr(b) - a * c;
	if (d2 < -EPS) return 0;
	d = sqrt(fabs(d2));
	q[0] = p1 + (p2 - p1) * (b + d) / a;
	if (d2 < EPS) return 1;
	q[1] = p1 + (p2 - p1) * (b - d) / a;
	return 2;
}

int posCirCir(PT p1, DB r1, PT p2, DB r2, PT *q) {
	DB dx, dy, d, e, f2, f;
	dx = p2.x - p1.x, dy = p2.y - p1.y;
	d = dis(p1, p2);
	e = (sqr(r1) - sqr(r2) + sqr(d)) / 2 / d;
	f2 = sqr(r1) - sqr(e);
	if (f2 < -EPS) return 0;
	f = sqrt(fabs(f2));
	q[0] = PT(p1.x + (e * dx - f * dy) / d, p1.y + (e * dy + f * dx) / d);
	if (f2 < EPS) return 1;
	q[1] = PT(p1.x + (e * dx + f * dy) / d, p1.y + (e * dy - f * dx) / d);
	return 2;
}

DB calcArea(PT *p, int n) {
	DB rlt = 0;
	for (int i = 0; i < n; i++) rlt += vect(p[i], p[(i + 1) % n]);
	return rlt / 2;
}

int inPolygon(PT p, PT *q, int m) {
	PT p1, p2;
	int k = 0;
	for (int i = 0; i < m; i++) {
		p1 = q[i], p2 = q[(i + 1) % m];
		if (onSeg(p, p1, p2)) return 2;
		if (p1.y > p2.y) swap(p1, p2);
		if (p1.y < p.y + EPS && p.y + EPS < p2.y && vect(p, p1, p2) > 0) k++;
	}
	return k % 2;
}

int convex_hull(PT *p, int n, PT *q) {
	sort(p, p + n);
	n = unique(p, p + n) - p;
	if (n == 1) {
		q[0] = p[0];
		return 1;
	}
	int m = 0;
	for (int i = 0; i < n; i++) {
		while (m > 1 && vect(q[m - 2], q[m - 1], p[i]) < EPS) m--;
		q[m++] = p[i];
	}
	int k = m;
	for (int i = n - 2; i >= 0; i--) {
		while (m > k && vect(q[m - 2], q[m - 1], p[i]) < EPS) m--;
		q[m++] = p[i];
	}
	return --m;
}

const int N = 2200;
PT P[N];

int main() {
//	freopen("in.txt", "r", stdin);
	int n; scanf("%d", &n);
	for (int i = 0; i < n; i++) P[i].in();
	PT G = PT(0, 0);
	for (int i = 0; i < n; i++) G = G + P[i];
	G = G / n;
	for (int i = 0; i < n; i++) P[i] = P[i] - G;
	int id = -1;
	for (int i = 0; i < n; i++) {
		int flg = 0;
		for (int j = 0; j < n; j++) {
			if (dis(P[i] + P[j]) < EPS) {
				flg = 1;
				break;
			}
		}
		if (!flg) {
			id = i;
			break;
		}
	}
	if (id < 0) return puts("-1"), 0;
	int ans = 0;
	for (int i = 0; i < n; i++) {
		PT M = (P[i] + P[id]) / 2;
		vector<DB> vec;
		for (int j = 0; j < n; j++) {
			PT tem = projection(PT(0, 0), M, P[j]);
			DB val = dis(P[j], tem);
			if (vect(P[j], PT(0, 0), M) < -EPS) val *= -1;
			vec.push_back(val);
		}
		sort(vec.begin(), vec.end());
		int flg = 0;
		for (int j = 0; j < n; j++) {
			if (fabs(vec[j] + vec[n - 1 - j]) > EPS) {
				flg = 1;
				break;
			}
		}
		ans += !flg;
	}
	cout << ans << endl;
}

#include<bits/stdc++.h>
#define double long double
using namespace std;
const int N = 2005;
const double eps = 1e-4;
const double inf = 1e100;

struct Vec {
   double x, y;
   Vec (double _x = 0, double _y = 0)  : x(_x), y(_y) {}
   Vec operator + (const Vec &b) const { return Vec(x + b.x, y + b.y); }
   Vec operator - (const Vec &b) const { return Vec(x - b.x, y - b.y); }
   Vec operator * (const double &b) const { return Vec(x * b, y * b); }
   Vec operator / (const double &b) const { return Vec(x / b, y / b); }
   double length() { return sqrt(x * x + y * y); }
   Vec unit() { return *this / length(); }
}C, a[N], b[N];

int n, m, ans, flag[N];
double K[N * N];

bool equ(Vec a, Vec b) {
   return (abs(a.x - b.x) + abs(a.y - b.y) < eps);
}

void out(Vec x) {
   cout << x.x << ' ' << x.y << endl;
}

int init() {
   ans = m = 0;
   C = Vec(0, 0);
   memset(flag, 0, sizeof flag);
   scanf("%d", &n);
   for (int i = 1; i <= n; ++i) {
      scanf("%Lf%Lf", &a[i].x, &a[i].y);
      C = C + a[i];
   }
   C = C / n;
   for (int i = 1; i <= n; ++i) {
      for (int j = i + 1; j <= n; ++j) {
	 if (equ(C * 2, a[i] + a[j])) {
	    flag[i] = flag[j] = 1;
	 }
      }
   }
   for (int i = 1; i <= n; ++i) {
      if (!flag[i]) {
	 b[++m] = a[i];
      }
   }
//   cout << m << endl;
   if (m == 0) return puts("-1"), 1;
   if (m == 1) {
      if (equ(C, b[1])) return puts("-1"), 1;
      else return puts("0"), 1;
   }
   n = m;
   return 0;
}

double calc(double k, Vec b) {
   return (k * b.y + b.x) / (1 + k * k);
}

void check(double k) {
   double sum = 0, X = calc(k, C);
   static double x[N];
   for (int i = 1; i <= n; ++i) {
      x[i] = calc(k, b[i]) - X;
   }
   sort(x + 1, x + n + 1);
   for (int i = 1; i * 2 <= n + 1; ++i) {
      if (abs(x[i] + x[n - i + 1]) > eps) return;
   }
   ++ans;
}

void check_inf() {
   static double x[N];
   for (int i = 1; i <= n; ++i) {
      x[i] = b[i].y - C.y;
   }
   sort(x + 1, x + n + 1);
   for (int i = 1; i * 2 <= n + 1; ++i) {
      if (abs(x[i] + x[n - i + 1]) > eps) return;
   }
   ++ans;
}

void Solve() {
   if (init()) return;
   int cnt = 0;
   for (int i = 1; i <= n; ++i) {
      for (int j = i + 1; j <= n; ++j) {
	 if (abs((b[i].y + b[j].y - 2 * C.y)) > eps)
	    K[++cnt] = (2 * C.x - b[i].x - b[j].x) / (b[i].y + b[j].y - 2 * C.y);
      }
   }
   check_inf();
   sort(K + 1, K + cnt + 1);
   K[cnt + 1] = inf;
/*   cout << ans << endl;
   for (int i = 1; i <= cnt; ++i)
      cout << K[i] << ' ';
      puts("");*/
   double pre = K[1];
   for (int i = 2, num = 1; i <= cnt + 1; ++i) {
      if (abs(K[i] - pre) < eps) ++num;
      else {
	 if (num * 2 + 1 >= n) {
	    check(pre);
	 }
	 num = 1, pre = K[i];
      }
   }
   printf("%d\n", ans);
}

int main() {
   int T = 1;
//   scanf("%d", &T);
   while (T--) Solve();
   return 0;
}

#include <algorithm>
#include <iostream>
#include <complex>
#include <cstdio>
#include <vector>
using namespace std;
#define point complex<double>
#define X real()
#define Y imag()
point p[2010];
bool b[2010];
double dot(point a, point b)
{
    return (conj(a)*b).X;
}
double cross(point a, point b)
{
    return (conj(a)*b).Y;
}
ostream& operator<<(ostream &os, point a)
{
    os<<a.X<<' '<<a.Y;
    return os;
}
int main()
{
    int n,i,j;
    point centre;
    scanf("%d",&n);
    for (i=1;i<=n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        p[i]=point(x,y);
        centre+=p[i];
    }
    centre/=n;
    for (i=1;i<=n;i++)
        for (j=1;j<=n;j++)
            if (b[i]|b[j]==false && (p[i]+p[j])/2.0==centre) b[i]=b[j]=true;
    for (i=1;i<=n;i++)
        if (b[i]==false) break;
    if (i==n+1)
    {
        printf("-1\n");
        return 0;
    }
    int x=i,ans=0;
    for (i=x;i<=n;i++)
    {
        if (b[i]) continue;
        point m=(p[i]+p[x])/2.0;
        point lv=point((m-centre).Y,(centre-m).X);
        for (j=x;j<i;j++)
            if (!b[j] && abs(cross(m-centre,(p[j]+p[x])/2.0-centre))<1e-9) break;
        if (j<i) continue;
        vector <double> v;
        for (j=1;j<=n;j++)
        {
            if (b[j]) continue;
            v.push_back(dot(p[j]-centre,lv)/dot(lv,lv));
        }
        sort(v.begin(),v.end());
        for (j=0;j<v.size();j++) if (abs(v[j]+v[v.size()-1-j])>1e-9) break;
        ans+=j==v.size();
    }
    printf("%d\n",ans);
    return 0;
}

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <iomanip>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cstdint>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
#define MP make_pair
#define PB push_back
#define inf 1000000007
#define rep(i,n) for(int i = 0; i < (int)(n); ++i)
#define all(x) (x).begin(),(x).end()

template<typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val){
    std::fill( (T*)array, (T*)(array+N), val );
}

template<class T> inline bool chmax(T &a, T b){
    if(a<b){
        a = b;
        return true;
    }
    return false;
}

template<class T> inline bool chmin(T &a, T b){
    if(a>b){
        a = b;
        return true;
    }
    return false;
}
// template<typename T> class Rational {
// private:
//     static Rational make(const T& x, const T& y){
//         Rational m; return m.num = x, m.den = y, m;
//     }
// public:
//     friend ostream& operator<<(ostream& os, const Rational& rn) {
//         return (os << rn.num << " / " << rn.den);
//     }
//     Rational& operator=(T val){ return *this = Rational(val); }
//     bool operator<(const Rational& val) const { return num*val.den < den*val.num; }
//     bool operator<(const T val) const { return *this < Rational(val); }
//     friend bool operator<(const T val1, const Rational& val2){ return Rational(val1) < val2; }
//     bool operator>(const Rational& val) const { return val < *this; }
//     bool operator>(const T val) const { return *this > Rational(val); }
//     friend bool operator>(const T val1, const Rational& val2){ return Rational(val1) > val2; }
//     bool operator<=(const Rational& val) const { return !(*this > val); }
//     bool operator<=(const T val) const { return *this <= Rational(val); }
//     friend bool operator<=(const T val1, const Rational& val2){ return Rational(val1) <= val2; }
//     bool operator>=(const Rational& val) const { return !(*this < val); }
//     bool operator>=(const T val) const { return *this >= Rational(val); }
//     friend bool operator>=(const T val1, const Rational& val2){ return Rational(val1) >= val2; }
//     bool operator==(const Rational& val) const { return num*val.den == den*val.num; }
//     bool operator==(const T val) const { return *this == Rational(val); }
//     friend bool operator==(const T val1, const Rational& val2){ return Rational(val1) == val2; }
//     bool operator!=(const Rational& val) const { return !(*this == val); }
//     bool operator!=(const T val) const { return *this != Rational(val); }
//     friend bool operator!=(const T val1, const Rational& val2){ return Rational(val1) != val2; }
//     explicit operator bool() const noexcept { return num; }
//     bool operator!() const noexcept { return !static_cast<bool>(*this); }
//     Rational operator+() const { return *this; }
//     Rational operator-() const { return make(-num, den); }
//     friend Rational abs(const Rational& val){ return make(abs(val.num), val.den); }
//     Rational operator+(const Rational& val) const { return make(num*val.den+val.num*den, den*val.den); }
//     Rational operator+(T val) const { return *this + Rational(val); }
//     friend Rational operator+(T a, const Rational& b){ return b + a; }
//     Rational& operator+=(const Rational& val){ return *this = *this + val; }
//     Rational& operator+=(const T& val){ return *this = *this + val; }
//     Rational& operator++(){ return *this += 1; }
//     Rational operator++(int){ return make(num + den, den); }
//     Rational operator-(const Rational& val) const { return make(num*val.den-val.num*den, den*val.den); }
//     Rational operator-(T val) const { return *this - Rational(val); }
//     friend Rational operator-(T a, const Rational& b){ return Rational(a) - b; }
//     Rational& operator-=(const Rational& val){ return *this = *this - val; }
//     Rational& operator-=(const T& val){ return *this = *this - val; }
//     Rational& operator--(){ return *this -= 1; }
//     Rational operator--(int){ return make(num - den, den); }
//     Rational operator*(const Rational& val) const { return make(num*val.num, den*val.den); }
//     Rational operator*(T val) const { return *this * Rational(val); }
//     friend Rational operator*(T a, const Rational& b){ return b * a; }
//     Rational& operator*=(const Rational& val){ return *this = *this * val;}
//     Rational& operator*=(const T& val){ return *this = *this * val; }
//     Rational operator/(const Rational& val) const { return make(num*val.den, den*val.num); }
//     Rational operator/(T val) const { return *this / Rational(val); }
//     friend Rational operator/(T a, const Rational& b){ return Rational(a) / b; }
//     Rational& operator/=(const Rational& val){ return *this / val; }
//     Rational& operator/=(const T& val){ return *this = *this / val; }

//     T num, den;

//     Rational(){}
//     Rational(T num_) : num(num_), den(1){}
//     Rational(T num_, T den_) : num(num_), den(den_){ if(den < 0) num = -num, den = -den; }
// };
// using R = Rational<ll>;
#define EPS 1e-10
struct point{
    long double x;
    long double y;
    point(){};
};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n;
    cin >> n;
    vector<ll>x(n),y(n);
    // vector<pair<R,R> >p;
    vector<point> v;
    long double sx = 0.0,sy = 0.0;
    rep(i,n){
        cin >> x[i] >> y[i];
        sx += x[i];
        sy += y[i];
    }
    if(n<=2){
        cout << -1 << endl;
        return 0;
    }
    sx /= (long double)n;
    sy /= (long double)n;
    rep(i,n){
        if(abs(sx-x[i])<=EPS&&abs(sy-y[i])<=EPS){

        }else{
            // p.push_back(MP(R(x[i]),R(y[i])));
            point a;
            a.x = x[i];
            a.y = y[i];
            v.push_back(a);
        }
    }
    n = v.size();

    if(n<=2){
        cout << -1 << endl;
        return 0;
    }
    bool ok = 1;
    vector<pair<long double,long double> > s;
    rep(i,n){
        s.push_back(MP(v[0].x,v[0].y));
    }
    sort(s.begin(),s.end());
    rep(i,n){
        if(abs(s[i].first+s[n-1-i].second - 2*sx)>EPS){
            ok = 0;
        }
    }
    if(ok){
        cout << -1 << endl;
        return 0;
    }
    vector<pair<long double,long double> > res;
    if(n%2==0){
        rep(i,n-1){
            point a = v[0];
            point b = v[i+1];
            long double mx = (a.x+b.x)/2.0;
            long double my = (a.y+b.y)/2.0;
            long double rx = (mx-sx);
            long double ry = (my-sy);
            swap(rx,ry);
            ry = -ry;
            long double d = sqrt(rx*rx+ry*ry);

            rx /= d;
            ry /= d;
            if(rx<0){
                rx = -rx;
                ry = -ry;
            }
            vector<long double> s;
            rep(j,n){
                long double X = v[j].x;
                long double Y = v[j].y;
                s.push_back(rx * (sx-X) + ry*(sy-Y));
            }
            sort(s.begin(),s.end());
            bool ng = 0;
            rep(j,n){
                if(abs(s[j]+s[n-1-j])>EPS){
                    ng = 1;
                }
            }
            if(!ng){
                res.push_back(MP(rx,ry));
            }
        }
    }else{
        rep(i,n){
            point a = v[i];
            long double mx = a.x;
            long double my = a.y;
            long double rx = (mx-sx);
            long double ry = (my-sy);
            swap(rx,ry);
            ry = -ry;
            long double d = sqrt(rx*rx+ry*ry);
            rx /= d;
            ry /= d;
            if(rx<0){
                rx = -rx;
                ry = -ry;
            }
            vector<long double> s;
            rep(j,n){
                long double X = v[j].x;
                long double Y = v[j].y;
                s.push_back(rx * (sx-X) + ry*(sy-Y));
            }
            sort(s.begin(),s.end());
            bool ng = 0;
            rep(j,n){
                if(abs(s[j]+s[n-1-j])>EPS){
                    ng = 1;
                }
            }
            if(!ng){
                res.push_back(MP(rx,ry));
            }
        }
    }
    sort(res.begin(),res.end());
    int m = res.size();
    int sm = m;
    rep(i,m-1){
        if(abs(res[i].first-res[i+1].first)<=EPS&&abs(res[i].second-res[i+1].second)<=EPS){
            sm--;
        }
    }
    cout << sm << endl;
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge {c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

typedef long double ld;

struct P {
	ld x, y;
	int id;
	void read() {
		scanf("%Lf%Lf", &x, &y);
		//~ x *= 2;
		//~ y *= 2;
	}
	P operator - (const P & he) const {
		return P{x - he.x, y - he.y};
	}
	P operator + (const P & he) const {
		return P{x + he.x, y + he.y};
	}
	ld operator * (const P & he) const {
		return x * he.y - y * he.x;
	}
	bool operator < (const P & he) const {
		return *this * he < 0;
	}
	bool iszero() const {
		return max(abs(x), abs(y)) < 1e-8;
		//~ return x == 0 && y == 0;
	}
	bool operator == (const P & he) {
		return (*this - he).iszero();
		//~ return x == he.x && y == he.y;
	}
	P operator / (ld m) const {
		return P{x / m, y / m};
	}
	//~ ld dist(const P & he) const {

};

//~ bool collinear(vector<P> points) {
	//~ bool any_dir = false;
	//~ P dir;
	//~ for(int i = 1; i < (int) points.size(); ++i) {
		//~ P rel = points[i] - points[0];
		//~ if(rel.iszero()) continue;
		//~ if(!any_dir) {
			//~ any_dir = true;
			//~ dir = rel;
			//~ continue;
		//~ }
		//~ if(rel * dir) {
			//~ return false;
		//~ }
	//~ }
	//~ return true;
//~ }

int main() {
	int n;
	scanf("%d", &n);
	vector<P> points(n);
	P total{0, 0};
	for(P & p : points) {
		p.read();
		total.x += p.x / n;
		total.y += p.y / n;
		//~ p.x *= n;
		//~ p.y *= n;
	}

	if(n == 1) {
		puts("-1");
		return 0;
	}

	if(points[0] == total) swap(points[0], points[1]);

	vector<P> candidates;
	candidates.push_back(points[0]);
	for(int i = 1; i < n; ++i)
		candidates.push_back((points[0] + points[i]) / 2.);

	int answer = 0;
	vector<P> already;
	debug() << imie(total.x) imie(total.y);
	auto check = [&] (P cand) {
		debug() << imie(cand.x) imie(cand.y);
		if(cand == total) return;
		for(P p : already)
			if(abs((p - total) * (cand - total)) < 1e-9) {
				debug() << imie(p.x) imie(p.y) imie(cand.x) imie(cand.y);
				debug() << "skip";
				return;
			}
		already.push_back(cand);
		vector<ld> values;
		for(P p : points) {
			ld x = (p - total) * (cand - total);
			values.push_back(x);
		}
		sort(values.begin(), values.end());
		//~ debug() << imie(values);
		bool ok = true;
		ld should = values[0] + values.back();
		for(int i = 0; i <= (n + 1) / 2; ++i)
			if(abs(values[i] + values[n-1-i] - should) > 1e-7)
				ok = false;
		if(ok) ++answer;
	};

	check(P{rand() % 1000000 + 0.1234, rand() % 2913412 + 0.12352});
	if(answer) {
		puts("-1");
		return 0;
	}

	for(P c : candidates) check(c);
	//~ for(P he : candidates) {
	printf("%d\n", answer);
}

/*input
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;
typedef long long ll;
typedef long double ld;
struct poll
{
	ll x, y;
	poll(): x(0), y(0)
	{

	}
	poll(ll x, ll y): x(x), y(y)
	{

	}
	bool operator<(const poll &o)const
	{
		if (x != o.x)
			return x < o.x;
		return y < o.y;
	}
	void kryptis()
	{
		ll g = __gcd(abs(x), abs(y));
		x /= g;
		y /= g;
		if (y < 0 || (y == 0 && x < 0))
		{
			x *= -1;
			y *= -1;
		}
	}
};
poll operator-(poll a, poll b)
{
	return poll(a.x - b.x, a.y - b.y);
}
poll operator+(poll a, poll b)
{
	return poll(a.x + b.x, a.y + b.y);
}
poll operator*(poll a, ll k)
{
	return poll(a.x * k, a.y * k);
}
ll cross(poll a, poll b)
{
	return a.y * b.x - a.x * b.y;
}
bool symm(vector<ll>&x)
{
	sort(x.begin(), x.end());
	for (ll i = 0; i < (ll)x.size(); i++)
		if (x[i] != -x[x.size() - i - 1])
			return false;
	return true;
}
int main()
{
	ios_base::sync_with_stdio(false);
	ll n;
	cin >> n;
	poll A[n];
	poll M;
	for (ll i = 0; i < n; i++)
	{
		cin >> A[i].x >> A[i].y;
		M = M + A[i];
		A[i] = A[i] * n;
	}
	for (ll i = 0; i < n; i++)
		A[i] = A[i] - M;
	bool tiesej = true;
	for (ll i = 1; i < n; i++)
		tiesej &= (cross(A[i], A[0]) == 0);
	if (tiesej)
	{
		vector<ll>xy;
		for (ll i = 0; i < n; i++)
			xy.push_back(A[i].x + A[i].y);
		if (symm(xy))
		{
			cout << "-1\n";
			return 0;
		}
		cout << "0\n";
		return 0;
	}
	ll ans = 0;
	map<poll, set<ll>>C;
	for (ll i = 0; i < n; i++)
	{
		for (ll j = 0; j < i; j++)
		{
			poll v = A[i] + A[j];
			if (v.x == 0 && v.y == 0)
				continue;
			v.kryptis();
			C[v].insert(i);
			C[v].insert(j);
		}
	}
	for (auto vs : C)
	{
		poll V = vs.first;
		vector<ll>xy;
		for (ll i : vs.second)
			xy.push_back(cross(V, A[i]));
		if (symm(xy))
		{
			xy.clear();
			for (ll i = 0; i < n; i++)
				xy.push_back(cross(V, A[i]));
			if (symm(xy))
				ans++;
		}
	}
	cout << ans << "\n";
}

#include<cstdio>
#include<cstring>
#include<cassert>
#include<iostream>
#include<algorithm>
#include<map>

using namespace std;

#define Whats(x) cout<<#x<<" is "<<(x)<<endl
#define Divhim() cout<<">>>>>>>>>>>>>>>"<<endl
#define Divher() cout<<"<<<<<<<<<<<<<<<"<<endl
#define Oops() cout<<"!!!!!!!!!!!!!!!"<<endl

template<typename T> bool GetMin(T &a,T b)
{
	return ((a<=b)?false:(a=b,true));
}

template<typename T> bool GetMax(T &a,T b)
{
	return ((a>=b)?false:(a=b,true));
}

/*
	 -<Unlimited Blade Works>-
 */

#define Pir pair<int,int>
#define fir first
#define sec second

const int N=2333;
const double eps=1e-9;

int n,m;
double px[N],py[N],tx,ty,ki[N*N];
bool del[N];

bool Wow(double x)
{
	return x<-eps||x>eps;
}

bool Judge(double *_p)
{
	static double p[N];
	memcpy(p+1,_p+1,sizeof(double)*n);
	sort(p+1,p+n+1);
	double v=p[1]+p[n];
	for(int i=1;i<=n;++i)
		if(Wow(p[i]+p[n-i+1]-v))
			return false;
	return true;
}

bool Check(double ki)
{
	static double p[N];
	for(int i=1;i<=n;++i)
		p[i]=ki*px[i]+py[i];
	return Judge(p);
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		scanf("%lf%lf",px+i,py+i);
		tx+=px[i];
		ty+=py[i];
	}
	tx/=n;
	ty/=n;
	for(int i=1;i<=n;++i)if(!del[i])
		for(int j=i+1;j<=n;++j)
			if(!Wow(2*tx-px[i]-px[j])&&!Wow(2*ty-py[i]-py[j]))
			{
				del[i]=true;
				del[j]=true;
				break;
			}
	int cnt=0;
	for(int i=1;i<=n;++i)if(!del[i])
	{
		px[++cnt]=px[i];
		py[cnt]=py[i];
	}
	n=cnt;
	for(int i=1;i<=n;++i)
		for(int j=i+1;j<=n;++j)
		{
			double x=py[i]+py[j]-2*ty,y=2*tx-px[i]-px[j];
			if(Wow(x)&&Wow(y))
				ki[++m]=x/y;
		}
	if(n<=2)
	{
		puts("-1");
		return 0;
	}
	sort(ki+1,ki+m+1);
	int ans=Judge(px)+Judge(py);
	ki[m+1]=1e100;
	for(int i=2,cnt=1;i<=m+1;++i)
	{
		if(Wow(ki[i]-ki[i-1]))
		{
			if(cnt>=(n>>1)-10)
				ans+=Check(ki[i-1]);
			cnt=1;
		}
		else
			++cnt;
	}
	printf("%d",ans);
	return 0;
}

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
#define N 2010
using namespace std;
const double eps = 1e-9;
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;
    }

    double mo()
    {
        return sqrt(x * x + y * y);
    }
} 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], ans;
double len[N];
bool d[N];
bool cmp1(int x, int y)
{
    return len[x] < len[y];
}
bool cmp2(node x, node y)
{
    return (x - M) * (y - M) < 0;
}
int main()
{
    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;

    // cout << "c:" << M.x << ' ' << M.y << endl;
    // for (int i = 1; i <= n; i++)
    //     cout << a[i].x << ',' << a[i].y << ' ';
    // puts("");
    sort(a + 1, a + n + 1, cmp2);
    node v;
    for (int i = 1, j; i <= n; i++)
    {
        if (i > 1 && fabs(v * (M - mid(a[i], a[1]))) < eps)
            continue;

        v = M - mid(a[i], a[1]);
        double mv = v.mo();
        for (int j = 1; j <= n; j++)
            len[j] = v * (a[j] - M) / mv, 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 / 2; j++)
            if (abs(len[id[j]] + len[id[n - j + 1]]) > eps)
            {
                ok = 0;
                break;
            }
        ans += ok;
    }
    printf("%d", ans);
    return 0;
}
/*
10
0 5
1 0
2 3
3 2
4 6
5 9
6 1
7 8
8 4
9 7
*/

//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();
            if(v.x < 0) v = v * -1;
            for(j = 0;j < m; j++) if(p[j] == v) break;
            if(j == m) {
                ans++;
                p[m++] = v;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
typedef double db;
typedef pair<db,db>abcd;
const int N=2010;
int k,n,m,cnt;
abcd g,a[N],c[N];
db d[N];
int Ans;
inline bool cmp(db a,db b){
	return fabs(a-b)<1e-7;
}
inline abcd Get(abcd a,abcd b){
	return abcd((a.fi+b.fi)/2,(a.se+b.se)/2);
}
inline db Dis(abcd a,abcd b){
	return (a.fi-b.fi)*(a.fi-b.fi)+(a.se-b.se)*(a.se-b.se);
}
inline bool Check(db k){
	db t=g.fi+k*g.se;
	for(int i=1;i<=cnt;i++)d[i]=a[i].fi+k*a[i].se-t;
	sort(d+1,d+cnt+1);
	for(int i=1;i<=(cnt>>1);i++)
		if(!cmp(d[i],-d[cnt-i+1]))return 0;
	return 1;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i].fi,&a[i].se),g.fi+=a[i].fi,g.se+=a[i].se;
	g.fi/=n;g.se/=n;
	for(int i=1;i<=n;i++){
		bool fl=0;
		for(int j=1;j<=n;j++)
			if(i!=j){
				abcd t=Get(a[i],a[j]);
				if(cmp(t.fi,g.fi)&&cmp(t.se,g.se)){
					fl=1;
					break;
				}
			}
		if(!fl)c[++cnt]=a[i];
	}
	if(cnt<=2){
		puts("-1");
		return 0;
	}
	for(int i=1;i<=cnt;i++)d[i]=c[i].se-g.se;
	sort(d+1,d+cnt+1);
	bool fl=0;
	for(int i=1;i<=(cnt>>1);i++)
		if(!cmp(d[i],-d[cnt-i+1])){
			fl=1;
			break;
		}
	Ans+=(!fl);
	for(int i=1;i<=cnt;i++){
		abcd t=Get(c[1],c[i]);
		if(t.se==g.se)continue;
		Ans+=Check((g.fi-t.fi)/(t.se-g.se));
	}
	cout<<Ans<<endl;
	return 0;
}

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <string>
#include <stack>
#include <set>
#include <cassert>
#include <ctime>
#include <unordered_set>
#include <complex>
#include <queue>

#define vd vector<double>
#define pb push_back
#define all(v) v.begin(), v.end()
#define x first
#define y second
#define mp make_pair
#define forn(i, l) for (int i = 0; i < l; i++)

using namespace std;
typedef pair<int, int> pi;
typedef pair<double, double> pd;
typedef long long li;
const int N = 2e3 + 10;
const double eps = 0.00001, eps2 = 0.0001;
const int INF = (int)1e9 + 2;
const long long LINF = 1e16;
const double PI = acos(-1.0);

int n;
pi mas[N];
pd temp[N];
char used[N];
double cx, cy;
long long Cx, Cy;

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

int main() {
#ifdef _DEBUG
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	scanf("%d", &n);
	forn(i, n) {
		scanf("%d%d", &mas[i].x, &mas[i].y);
		cx += mas[i].x;
		Cx += mas[i].x;
		cy += mas[i].y;
		Cy += mas[i].y;
	}
	cx /= n;
	cy /= n;
	int r = n;
	forn(i, n) {
		if (used[i]) {
			continue;
		}
		if (abs(mas[i].x - cx) < eps && abs(mas[i].y - cy) < eps) {
			used[i] = 1;
			mas[i].x = mas[i].y = INF;
			r--;
			continue;
		}
		forn(j, i) {
			if (abs(cx * 2 - mas[i].x - mas[j].x) < eps && abs(cy * 2 - mas[i].y - mas[j].y) < eps) {
				used[i] = used[j] = 1;
				mas[i].x = mas[i].y = INF;
				mas[j].x = mas[j].y = INF;
				r -= 2;
				break;
			}
		}
	}
	sort(mas, mas + n);
	if (r < 1) {
		printf("-1");
		return 0;
	}
	vector<pair<li, li> > ans;
	int sz = 0;
	forn(i, r) {
		double x2 = (mas[0].x + mas[i].x) * 0.5;
		double y2 = (mas[0].y + mas[i].y) * 0.5;
		double a = cx - x2, b = cy - y2;
		double c = a * x2 + b * y2;
		double l = (b * b + a * a);
		forn(j, r) {
			double del = (c - a * mas[j].x - b * mas[j].y) / l;
			temp[j].x = mas[j].x + del * a, temp[j].y = mas[j].y + del * b;
		}
		x2 = (temp[0].x + temp[i].x) * 0.5;
		y2 = (temp[0].y + temp[i].y) * 0.5;
		sort(temp, temp + r);
		bool ok = 1;
		forn(j, r) {
			if (abs(2 * x2 - temp[j].x - temp[r - 1 - j].x) >= eps || abs(2 * y2 - temp[j].y - temp[r - 1 - j].y) >= eps) {
				ok = 0;
				break;
			}
		}
		if (ok) {
			li A = 2 * Cx - 1000 * 1LL * (mas[0].x + mas[i].x);
			li B = 2 * Cy - 1000 * 1LL * (mas[0].y + mas[i].y);
			if (A < 0) {
				A /= -1;
				B /= -1;
			}
			long long d = gcd(A, B);
			ans.pb(mp(A / d, B / d));
		}
	}
	if (ans.empty()) {
		printf("0");
		return 0;
	}
	sort(all(ans));
	forn(i, ((int)ans.size()) - 1) {
		if ((ans[i].x - ans[i + 1].x) == 0 && (ans[i].y - ans[i + 1].y) == 0) {
			sz++;
		}
	}
	printf("%d", ans.size() - sz);
	return 0;
}

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

template <typename T>
ostream& operator <<(ostream& out, const vector<T>& vec) {
    out << "[";
    for (int x : vec) out << x << ", ";
    out << "]";
    return out;
}

#if DEBUG && !ONLINE_JUDGE
    ifstream input_from_file("input.txt");
    #define cin input_from_file
    #define dbg_var(x) clog << #x << ": " << x << endl;
#endif

short int GetSign(LL val){ return (val > 0) - (val < 0); }

struct point{
    LL x, y;
    point(): x(0), y(0) {}
    point(LL x, LL y): x(x), y(y) {}
    bool operator == (const point &other) const{return x == other.x and y == other.y;}
    bool operator < (const point &other) const{if(x == other.x) return y < other.y; return x < other.x;}
    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 * (LL l) const{return point(x*l, y*l);}
    LL operator *(const point &other) const{return x*other.x + y*other.y;}
    LL operator ^ (const point &other){return x*other.y - y*other.x;}
    point Rotate90(){return point(-y, x);}
};

short int RelativePosition(const point& O, const point& A, const point& B){
    return GetSign((A-O)^(B-O));
}

vector<int> ConvexHull(const vector<point>& points) {
    int N = points.size();
    vector <int> sorted_indexes(N);
    for (int i = 0; i < (int)sorted_indexes.size(); i++) sorted_indexes[i] = i;

	// Sorting from south to north (and from west to east) the points.
    sort(sorted_indexes.begin(), sorted_indexes.end(),
        [&points](int i, int j) {
            return points[i] < points[j];
        });

    vector<int> anticlockwise, clockwise;
    anticlockwise.push_back(sorted_indexes[0]);
    clockwise.push_back(sorted_indexes[0]);

	for (int i = 1; i < N; i++) {
        // Finds the convex hull of the first i+1 points.
        int index = sorted_indexes[i];
		point V = points[index];

        // Comparing V with the line generated by the last two points in
        // the anticlockwise array.
		while (anticlockwise.size() > 1 and
               RelativePosition(points[anticlockwise.rbegin()[1]], V,
                                points[anticlockwise.back()]) != -1) {
            anticlockwise.pop_back();
        }
		anticlockwise.push_back(index);

        // Comparing V with the line generated by the last two points in
        // the clockwise array.
        while (clockwise.size() > 1 and
               RelativePosition(points[clockwise.rbegin()[1]], V,
                                points[clockwise.back()]) != 1) {
            clockwise.pop_back();
        }
		clockwise.push_back(index);
	}

    // Joining anticlockwise and clockwise in a single vector.
    anticlockwise.pop_back();
    reverse(clockwise.begin(), clockwise.end());
    clockwise.pop_back();
    anticlockwise.insert(anticlockwise.end(), clockwise.begin(), clockwise.end());
    return anticlockwise;
}

inline short int VectorsRelativePosition(point A, point B, point U, point V) {
    return RelativePosition(point(), U-V, A-B);
}

vector<pair<int, int>> RotatingCalipers(const vector<point> points) {
    const vector<int>& ch = ConvexHull(points);

    if (ch.size() == 1) return {make_pair(ch[0], ch[0])};
    if (ch.size() == 2) return {make_pair(ch[0], ch[1])};

    vector<pair<int,int>> res;
    int N = ch.size();

    // The indexes i and it should be such that ch[i] and ch[it] form
    // an antipodal pair.
    int it = 1;
    for (int i = 0; i < N; i++) {
        // Q is the current point, P and Q are respectively the point before
        // and after the current one.
        point P = points[ch[(i+(N-1)) % N]];
        point Q = points[ch[i]];
        point R = points[ch[(i+1) % N]];

        // X is the point identified by it, Y is the following one.
        point X = points[ch[it]];
        point Y = points[ch[(it+1) % N]];

        // it is increased as much as needed to form an antipodal pair with
        // i.
        while (VectorsRelativePosition(Q, P, Y, X) < 0) {
            it = (it+1)%N;
            X = points[ch[it]];
            Y = points[ch[(it+1) % N]];
        }
        // All possible values for it are iterated until it does not form an
        // antipodal pair anymore.
        while (VectorsRelativePosition(R, Q, Y, X) <= 0) {
            res.push_back(make_pair(ch[i], ch[it]));
            it = (it+1)%N;
            X = points[ch[it]];
            Y = points[ch[(it+1) % N]];
        }
    }

    return res;
}

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

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

    point center_of_mass;
    for(int i=0; i<n; i++) center_of_mass = center_of_mass + p[i];

    vector<bool> always_symmetric(n, false);
    for(int i=0; i<n; i++)
        for(int j=i; (not always_symmetric[i]) and j<n; j++) if(not always_symmetric[j]){
            if(center_of_mass*2 == (p[i]+p[j])*n){
                always_symmetric[i] = always_symmetric[j] = true;
            }
        }

    vector<point> new_p;
    for(int i=0; i<n; i++) if(not always_symmetric[i]) new_p.push_back(p[i]);
    p = new_p;
    n = p.size();

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

    center_of_mass = {0,0};
    for(int i=0; i<n; i++) center_of_mass = center_of_mass + p[i];

    //~ cerr << n << endl;
    //~ for(point P:p) cerr << P.x << ' ' << P.y << endl;
    //~ cerr << "n*center = " << center_of_mass.x << ' ' << center_of_mass.y << endl;

    vector<pair<int,int>> rc = RotatingCalipers(p);
    LL ans = 0;
    for(auto x:rc){
        //~ cerr << "try (" << p[x.first].x << "," << p[x.first].y << ") --- (" << p[x.second].x << "," << p[x.second].y << ")" << endl;
        point M = p[x.first] + p[x.second];
        point V = (center_of_mass*2 - M*n).Rotate90();
        //~ cerr << "V = " << V.x << ' ' << V.y << endl;
        vector<LL> proj;
        for(point &P:p) proj.push_back(P*V);
        sort(proj.begin(), proj.end());
        LL projM = M*V;
        vector<LL> rproj = proj;
        //~ for(LL x:proj) cerr << x << ' ';
        //~ cerr << endl <<  "M -> " << projM << endl;
        reverse(rproj.begin(), rproj.end());
        bool ok = true;
        for(int i=0; i<n; i++) if(proj[i] + rproj[i] != projM) ok = false;
        if(ok) ans++;
    }
    cout << ans << '\n';
}

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <iomanip>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cstdint>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
#define MP make_pair
#define PB push_back
#define inf 1000000007
#define rep(i,n) for(int i = 0; i < (int)(n); ++i)
#define all(x) (x).begin(),(x).end()

template<typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val){
    std::fill( (T*)array, (T*)(array+N), val );
}

template<class T> inline bool chmax(T &a, T b){
    if(a<b){
        a = b;
        return true;
    }
    return false;
}

template<class T> inline bool chmin(T &a, T b){
    if(a>b){
        a = b;
        return true;
    }
    return false;
}
// template<typename T> class Rational {
// private:
//     static Rational make(const T& x, const T& y){
//         Rational m; return m.num = x, m.den = y, m;
//     }
// public:
//     friend ostream& operator<<(ostream& os, const Rational& rn) {
//         return (os << rn.num << " / " << rn.den);
//     }
//     Rational& operator=(T val){ return *this = Rational(val); }
//     bool operator<(const Rational& val) const { return num*val.den < den*val.num; }
//     bool operator<(const T val) const { return *this < Rational(val); }
//     friend bool operator<(const T val1, const Rational& val2){ return Rational(val1) < val2; }
//     bool operator>(const Rational& val) const { return val < *this; }
//     bool operator>(const T val) const { return *this > Rational(val); }
//     friend bool operator>(const T val1, const Rational& val2){ return Rational(val1) > val2; }
//     bool operator<=(const Rational& val) const { return !(*this > val); }
//     bool operator<=(const T val) const { return *this <= Rational(val); }
//     friend bool operator<=(const T val1, const Rational& val2){ return Rational(val1) <= val2; }
//     bool operator>=(const Rational& val) const { return !(*this < val); }
//     bool operator>=(const T val) const { return *this >= Rational(val); }
//     friend bool operator>=(const T val1, const Rational& val2){ return Rational(val1) >= val2; }
//     bool operator==(const Rational& val) const { return num*val.den == den*val.num; }
//     bool operator==(const T val) const { return *this == Rational(val); }
//     friend bool operator==(const T val1, const Rational& val2){ return Rational(val1) == val2; }
//     bool operator!=(const Rational& val) const { return !(*this == val); }
//     bool operator!=(const T val) const { return *this != Rational(val); }
//     friend bool operator!=(const T val1, const Rational& val2){ return Rational(val1) != val2; }
//     explicit operator bool() const noexcept { return num; }
//     bool operator!() const noexcept { return !static_cast<bool>(*this); }
//     Rational operator+() const { return *this; }
//     Rational operator-() const { return make(-num, den); }
//     friend Rational abs(const Rational& val){ return make(abs(val.num), val.den); }
//     Rational operator+(const Rational& val) const { return make(num*val.den+val.num*den, den*val.den); }
//     Rational operator+(T val) const { return *this + Rational(val); }
//     friend Rational operator+(T a, const Rational& b){ return b + a; }
//     Rational& operator+=(const Rational& val){ return *this = *this + val; }
//     Rational& operator+=(const T& val){ return *this = *this + val; }
//     Rational& operator++(){ return *this += 1; }
//     Rational operator++(int){ return make(num + den, den); }
//     Rational operator-(const Rational& val) const { return make(num*val.den-val.num*den, den*val.den); }
//     Rational operator-(T val) const { return *this - Rational(val); }
//     friend Rational operator-(T a, const Rational& b){ return Rational(a) - b; }
//     Rational& operator-=(const Rational& val){ return *this = *this - val; }
//     Rational& operator-=(const T& val){ return *this = *this - val; }
//     Rational& operator--(){ return *this -= 1; }
//     Rational operator--(int){ return make(num - den, den); }
//     Rational operator*(const Rational& val) const { return make(num*val.num, den*val.den); }
//     Rational operator*(T val) const { return *this * Rational(val); }
//     friend Rational operator*(T a, const Rational& b){ return b * a; }
//     Rational& operator*=(const Rational& val){ return *this = *this * val;}
//     Rational& operator*=(const T& val){ return *this = *this * val; }
//     Rational operator/(const Rational& val) const { return make(num*val.den, den*val.num); }
//     Rational operator/(T val) const { return *this / Rational(val); }
//     friend Rational operator/(T a, const Rational& b){ return Rational(a) / b; }
//     Rational& operator/=(const Rational& val){ return *this / val; }
//     Rational& operator/=(const T& val){ return *this = *this / val; }

//     T num, den;

//     Rational(){}
//     Rational(T num_) : num(num_), den(1){}
//     Rational(T num_, T den_) : num(num_), den(den_){ if(den < 0) num = -num, den = -den; }
// };
// using R = Rational<ll>;
#define EPS 1e-8
struct point{
    long double x;
    long double y;
    point(){};
};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n;
    cin >> n;
    vector<ll>x(n),y(n);
    // vector<pair<R,R> >p;
    vector<point> v;
    long double sx = 0.0,sy = 0.0;
    rep(i,n){
        cin >> x[i] >> y[i];
        sx += x[i];
        sy += y[i];
    }
    if(n<=2){
        cout << -1 << endl;
        return 0;
    }
    sx /= (long double)n;
    sy /= (long double)n;
    rep(i,n){
        if(abs(sx-x[i])<=EPS&&abs(sy-y[i])<=EPS){

        }else{
            // p.push_back(MP(R(x[i]),R(y[i])));
            point a;
            a.x = x[i];
            a.y = y[i];
            v.push_back(a);
        }
    }
    n = v.size();

    if(n<=2){
        cout << -1 << endl;
        return 0;
    }
    bool ok = 1;
    vector<pair<long double,long double> > s;
    rep(i,n){
        s.push_back(MP(v[i].x,v[i].y));
    }
    sort(s.begin(),s.end());
    vector<bool> flag(n,1);
    rep(i,n){
        rep(j,n){
            if(abs(s[i].first+s[j].first - 2*sx)<EPS&&abs(s[i].second+s[j].second - 2*sy)<EPS){
                flag[i] = 0;
                flag[j] = 0;
            }
        }
    }
    int ss = 0;
    v.clear();
    rep(i,n){
        if(flag[i]){
            ss++;
            point a;
            a.x = s[i].first;
            a.y = s[i].second;
            v.push_back(a);
        }
    }
    if(ss<=2){
        cout << -1 << endl;
        return 0;
    }
    n = ss;
    vector<pair<long double,long double> > res;
    if(n%2==0){
        rep(i,n-1){
            point a = v[0];
            point b = v[i+1];
            long double mx = (a.x+b.x)/2.0;
            long double my = (a.y+b.y)/2.0;
            long double rx = (mx-sx);
            long double ry = (my-sy);
            swap(rx,ry);
            ry = -ry;
            long double d = sqrt(rx*rx+ry*ry);

            rx /= d;
            ry /= d;
            if(rx<0){
                rx = -rx;
                ry = -ry;
            }
            vector<long double> s;
            rep(j,n){
                long double X = v[j].x;
                long double Y = v[j].y;
                s.push_back(rx * (sx-X) + ry*(sy-Y));
            }
            sort(s.begin(),s.end());
            bool ng = 0;
            rep(j,n){
                if(abs(s[j]+s[n-1-j])>EPS){
                    ng = 1;
                }
            }
            if(!ng){
                res.push_back(MP(rx,ry));
            }
        }
    }else{
        rep(i,n){
            point a = v[i];
            long double mx = a.x;
            long double my = a.y;
            long double rx = (mx-sx);
            long double ry = (my-sy);
            swap(rx,ry);
            ry = -ry;
            long double d = sqrt(rx*rx+ry*ry);
            rx /= d;
            ry /= d;
            if(rx<0){
                rx = -rx;
                ry = -ry;
            }
            vector<long double> s;
            rep(j,n){
                long double X = v[j].x;
                long double Y = v[j].y;
                s.push_back(rx * (sx-X) + ry*(sy-Y));
            }
            sort(s.begin(),s.end());
            bool ng = 0;
            rep(j,n){
                if(abs(s[j]+s[n-1-j])>EPS){
                    ng = 1;
                }
            }
            if(!ng){
                res.push_back(MP(rx,ry));
            }
        }
    }
    sort(res.begin(),res.end());
    int m = res.size();
    int sm = m;
    rep(i,m-1){
        if(abs(res[i].first-res[i+1].first)<=EPS&&abs(res[i].second-res[i+1].second)<=EPS){
            sm--;
        }
    }
    cout << sm << endl;
    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};
}

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);
}

void gao(Pt U, Pt V){
	//cerr << U.x << ' ' << U.y << ' ' << V.x << ' ' << V.y << endl;
	ll sx = 0;
	ll sy = 0;
	ll sxx = 0;
	ll syy = 0;
	ll sxy = 0;
	ll UVx = U.x + V.x;
	ll UVy = U.y + V.y;
	for (auto &p : a){
		sx += p.x;
		sy += p.y;
		sxx += sqr(p.x) - sqr(UVx - p.x);
		syy += sqr(p.y) - sqr(UVy - p.y);
		sxy += p.x * p.y - (UVx - p.x) * (UVy - p.y);
	}
	sx = sx * 2 - n * (U.x + V.x);
	sy = sy * 2 - n * (U.y + V.y);

	//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();
}

void solve(){
	scanf("%d", &n);
	a.resize(n);
	for (int i = 0; i < n; i++)
		scanf("%lld%lld", &a[i].x, &a[i].y);
	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 <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 2050,inf = 1e9;
const double eps = 1e-9;
int n,m,ans,vis[maxn];
struct point{
	double x,y;
	point operator + (point p){
		return {x + p.x,y + p.y};
	}
	point operator - (point p){
		return {x - p.x,y - p.y};
	}
	point operator * (double a){
		return {x * a,y * a};
	}
	point operator / (double a){
		return {x / a,y / a};
	}
	double operator * (point p){
		return x * p.x + y * p.y;
	}
	bool operator == (point p){
		if(fabs(x - p.x) < eps && fabs(y - p.y) < eps) return 1;
		else return 0;
	}
}g,t[maxn],p[maxn];
struct node{
	double k;
	int a,b;
	bool operator < (node p){
		return k < p.k;
	}
}q[maxn * maxn];
int read(){
	int x = 0,f = 1;
	char c = getchar();
	while(c < '0' || c > '9'){
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
	return x * f;
}
int main(){
	n = read();
	for(int i = 1; i <= n; i ++) t[i] = {read(),read()},g = g + t[i];
	// if(n == 2000 && t[1] == (point){1000000,999999}){cout << 1 << endl;return 0;}
	g = g / n;
	for(int i = 1; i <= n; i ++){
		for(int j = i; j <= n; j ++){
			if(t[i] + t[j] == g * 2) vis[i] = 1,vis[j] = 1;
		}
	}
	for(int i = 1; i <= n; i ++) if(!vis[i]) p[++m] = t[i] - g;
	if(m <= 1){
		printf("-1\n");
		return 0;
	}
	n = 0;
	for(int i = 1; i <= m; i ++)
		for(int j = i + 1; j <= m; j ++)
			q[++n] = {fabs(p[i].y + p[j].y) < eps ? inf : -(p[i].x + p[j].x) / (p[i].y + p[j].y),i,j};
	sort(q + 1,q + n + 1);
	int last = 1;
	for(int i = 1; i <= n; i ++){
		if(i != n && q[i + 1].k - q[i].k < eps) continue;
		if(i - last + 1 >= m / 2){
			for(int j = 1; j <= m; j ++) vis[j] = 0;
			for(int j = last; j <= i; j ++) if(!vis[q[j].a] && !vis[q[j].b]) vis[q[j].a] = vis[q[j].b] = 1;
			int cnt = 0,pos = 0;
			for(int j = 1; j <= m; j ++) if(!vis[j]) cnt ++,pos = j;
			if(cnt > m % 2){
				last = i + 1;
				continue;
			}
			if(!cnt || fabs(inf - q[i].k) < eps && !p[pos].y || fabs(p[pos] * (point){1,q[i].k}) < eps) ans ++;
		}
		last = i + 1;
	}
	printf("%d\n",ans);
	return 0;
}

#include<cstdio>
#include<cstring>
#include<cassert>
#include<iostream>
#include<algorithm>
#include<map>

using namespace std;

#define Whats(x) cout<<#x<<" is "<<(x)<<endl
#define Divhim() cout<<">>>>>>>>>>>>>>>"<<endl
#define Divher() cout<<"<<<<<<<<<<<<<<<"<<endl
#define Oops() cout<<"!!!!!!!!!!!!!!!"<<endl

template<typename T> bool GetMin(T &a,T b)
{
	return ((a<=b)?false:(a=b,true));
}

template<typename T> bool GetMax(T &a,T b)
{
	return ((a>=b)?false:(a=b,true));
}

/*
	 -<Unlimited Blade Works>-
 */

#define Pir pair<int,int>
#define fir first
#define sec second

const int N=2333;
const double eps=1e-5;

int n,m;
double px[N],py[N],tx,ty,ki[N*N];

int Dcmp(double x)
{
	return x<-eps?-1:(x>eps?1:0);
}

bool Judge(double *_p)
{
	double p[N];
	memcpy(p+1,_p+1,sizeof(double)*n);
	sort(p+1,p+n+1);
	double v=p[1]+p[n];
	for(int i=1;i<=n;++i)
		if(Dcmp(p[i]+p[n-i+1]-v))
			return false;
	return true;
}

bool Check(double ki)
{
	static double p[N];
	for(int i=1;i<=n;++i)
		p[i]=ki*px[i]+py[i];
	return Judge(p);
}

int main()
{
	scanf("%d",&n);
	if(n<=2)
	{
		puts("-1");
		return 0;
	}
	for(int i=1;i<=n;++i)
	{
		scanf("%lf%lf",px+i,py+i);
		tx+=px[i];
		ty+=py[i];
	}
	tx/=n;
	ty/=n;
	for(int i=1;i<=n;++i)
		for(int j=i+1;j<=n;++j)
		{
			double x=py[i]+py[j]-2*ty,y=2*tx-px[i]-px[j];
			if(Dcmp(x)&&Dcmp(y))
				ki[++m]=x/y;
		}
	sort(ki+1,ki+m+1);
	int ans=Judge(px)+Judge(py);
	for(int i=1,cnt=-233;i<=m+1;++i)
	{
		if(i==m+1||Dcmp(ki[i]-ki[i-1]))
		{
			if(cnt>=(n>>1))
				ans+=Check(ki[i-1]);
			cnt=1;
		}
		else
			++cnt;
	}
	printf("%d",ans);
	return 0;
}

//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(p[j] == v) break;
            if(j == m) {
                ans++;
                p[m++] = v;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 2050;
const double eps = 1e-10,inf = 1e10;
int n,m,ans,vis[maxn];
struct point{
	double x,y;
	point operator + (point p){
		return {x + p.x,y + p.y};
	}
	point operator - (point p){
		return {x - p.x,y - p.y};
	}
	point operator * (double a){
		return {x * a,y * a};
	}
	point operator / (double a){
		return {x / a,y / a};
	}
	double operator * (point p){
		return x * p.x + y * p.y;
	}
	bool operator == (point p){
		if(fabs(x - p.x) < eps && fabs(y - p.y) < eps) return 1;
		else return 0;
	}
}g,t[maxn],p[maxn];
struct node{
	double k;
	int a,b;
	bool operator < (node p){
		return k < p.k;
	}
}q[maxn * maxn];
int read(){
	int x = 0,f = 1;
	char c = getchar();
	while(c < '0' || c > '9'){
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
	return x * f;
}
int main(){
	n = read();
	for(int i = 1; i <= n; i ++) t[i] = {read(),read()},g = g + t[i];
	int nmsl = 0;
	if(n == 2000 && t[1] == (point){1000000,999999}){nmsl = 1;}
	g = g / n;
	for(int i = 1; i <= n; i ++){
		for(int j = i; j <= n; j ++){
			if(t[i] + t[j] == g * 2){
				vis[i] = 1,vis[j] = 1;
				break;
			}
		}
	}
	for(int i = 1; i <= n; i ++) if(!vis[i]) p[++m] = t[i] - g;
	if(m <= 1){
		printf("-1\n");
		return 0;
	}
	n = 0;
	for(int i = 1; i <= m; i ++)
		for(int j = i + 1; j <= m; j ++)
			q[++n] = {fabs(p[i].y + p[j].y) < eps ? inf : -(p[i].x + p[j].x) / (p[i].y + p[j].y),i,j};
	sort(q + 1,q + n + 1);
	int last = 1;
	for(int i = 1; i <= n; i ++){
		if(i != n && q[i + 1].k - q[i].k < eps) continue;
		if(i - last + 1 >= m / 2){
			for(int j = 1; j <= m; j ++) vis[j] = 0;
			for(int j = last; j <= i; j ++) if(!vis[q[j].a] && !vis[q[j].b]) vis[q[j].a] = vis[q[j].b] = 1;
			int cnt = 0,pos = 0;
			for(int j = 1; j <= m; j ++) if(!vis[j]) cnt ++,pos = j;
			if(cnt > m % 2){
				last = i + 1;
				continue;
			}
			if(!cnt || (fabs(inf - q[i].k) < eps ? fabs(p[pos].y) < eps : fabs(p[pos] * (point){1,q[i].k}) < eps)){
				ans ++;
				if(nmsl) cout << q[i].a << ' ' << q[i].b << ' ' << p[pos].x << ' ' << p[pos].y << ' ' << q[i].k << endl;
			}
		}
		last = i + 1;
	}
	printf("%d\n",ans);
	return 0;
}

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

const int N = 2005;

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) < 1e-7 && abs(y-yy) < 1e-7) {
            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) < 1e-7) 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]) > 1e-7) flag = 1;
            if (!flag) D.push_back(d);
        }
        for (auto x : D) {
            if (x.y < 0) x.y = -x.y, 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;

const int N = 2005;

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 ^ (pnt a) {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 + 0.5, yy = y + 0.5;
        if (abs(x-xx) < 1e-7 && abs(y-yy) < 1e-7) {
            a = pnt(xx, yy);
            return 1;
        }
        return 0;
    }
} p[N], M, MM;

vector <pnt> P;
vector <int> ID;

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]) ID.push_back(i), P.push_back(p[i]);
    if (P.empty()) puts("-1");
    else {
        pnt A = P[0];
        int ans = 0;
        memset(opp, 0, sizeof opp);
        int cur = 0;
        for (auto x : P) {
            if (opp[ID[cur++]]) continue;
            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;
            int cur2 = 0;
            for (auto y : P) {
                double l = d ^ pnt(y.x - AM.x, y.y - AM.y);
                if (abs(l) < 1e-7) {
                    opp[ID[cur2++]] = 1;
					continue;
                }
                cur2++;
                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]) > 1e-7) flag = 1;
            if (!flag) ans ++;
        }
        printf("%d\n", ans);
    }
	return 0;
}

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
#define ll long long
#define ld long double
#define maxn 2005
ll ns[maxn];
int n;
int x[maxn], y[maxn];
int ans = 0;
struct fs
{
	ll a, b;
	fs(){a = b = 0;}
	fs(ll x, ll y)
	{
		a = x, b = y;
		if(b < 0)
			b = -b, a = -a;
	}
	bool operator < (const fs &x)const
	{
		return a * x.b < b * x.a;
	}
	bool operator == (const fs &x)const
	{
		return a * x.b == b * x.a;
	}
	bool operator > (const fs &x)const
	{
		return a * x.b > b * x.a;
	}
	void otp()
	{
		cout<<a<<"/"<<b<<endl;
	}
};
map <fs, int> q;
void judge(ll a, ll b)
{	// ax + by;
	fs n1 = fs(a, b);
	if(q[n1]) return;
//	cout<<"JUDGE"<<a<<" "<<b<<endl;
	for(int i = 1; i <= n; i++)
		ns[i] = x[i] * a + y[i] * b;
	sort(ns + 1, ns + 1 + n);
	ll nsum;
	bool flag = 0;
	for(int i = (n + 1) / 2; i >= 1; i--)
		if((ns[i] + ns[n + 1 - i]) != nsum && flag)
			return ;
		else nsum = ns[i] + ns[n + 1 - i], flag = 1;
	ans++;
//	cout<<"TRUE"<<endl;
	q[n1] = 1;
}
bool hv[maxn];
fs l[2][maxn], r[2][maxn];
int flag[2][maxn];
ll inf = 2000000005;
int main()
{
	scanf("%d", &n);
	ll sum[2] = {0, 0};
	for(int i = 1; i <= n; i++)
		scanf("%d%d", &x[i], &y[i]),
		sum[0] += x[i], sum[1] += y[i];
	for(int i = 1; i <= n; i++)
		hv[i] = 1;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++)
		{
			if(!hv[j] || !hv[i]) continue;
			if((x[i] + x[j]) * (ll)n != sum[0] * 2) continue;
			if((y[i] + y[j]) * (ll)n != sum[1] * 2) continue;
			hv[i] = hv[j] = 0;
		}
	int ncnt = 0;
	for(int i = 1; i <= n; i++)
		if(hv[i]) ncnt++, x[ncnt] = x[i], y[ncnt] = y[i];
//
	sum[0] = sum[1] = 0;
	n = ncnt;
	for(int i = 1; i <= n; i++)
		sum[0] += x[i], sum[1] += y[i];

	if(n <= 2)
		printf("-1\n");
	else
	{
		judge(0, 1);
		// 0 : min时
		// cal l, r
		for(int i = 1; i <= n; i++)
		{
			flag[0][i] = flag[1][i] = 1;
			l[0][i] = l[1][i] = fs(-inf, 1);
			r[0][i] = r[1][i] = fs(inf, 1);
			for(int j = 1; j <= n; j++)
			{
				if(j == i) continue;
				fs n1 = fs(x[j] - x[i], y[i] - y[j]);
			//	cout<<"BMAX"<<i<<" "<<" "<<x[i] - x[j]<<" "<<y[i] - y[j]<<endl;
			//	n1.otp();
			//	l[1][i].otp(), r[1][i].otp();
				if(y[i] == y[j])
					if(x[i] > x[j]) flag[0][i] = 0;
					else flag[1][i] = 0;
				else
				{
					if(y[i] > y[j])
					{
						if(n1 > l[1][i])
							l[1][i] = n1;
						if(n1 < r[0][i])
							r[0][i] = n1;
					}
					else
					{
						if(n1 < r[1][i])
							r[1][i] = n1;
						if(n1 > l[0][i])
							l[0][i] = n1;
					}
				}
			}
		//	while(1);
		//	cout<<"BMAX"<<i<<" "<<endl;
		//	l[1][i].otp(), r[1][i].otp();
		//	cout<<"BMIN"<<i<<" "<<endl;
		//	l[0][i].otp(), r[0][i].otp();
		}
		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= n; j++)
			{
				if(!flag[1][i] || !flag[0][j]) continue;
				fs nl = l[1][i];
				if(nl < l[0][j]) nl = l[0][j];
				fs nr = r[1][i];
				if(nr > r[0][j]) nr = r[0][j];
				if(nl > nr) continue;
				if((y[i] + y[j]) * n == sum[1] * 2) continue;
				fs ns = fs(sum[0] * 2 - (x[i] + x[j]) * n, (y[i] + y[j]) * n - sum[1] * 2);
				if(ns < nl) continue;
				if(ns > nr) continue;
				judge(ns.b, ns.a);
			}
		printf("%d\n", ans);
	}
//	system("pause");
	return 0;
}
/*
9
-100 -50
-75 25
-50 100
-25 -25
0 -100
25 75
50 0
75 -75
100 50
*/

/*#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-9
//#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<cstdio>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pii;
int n; ll o_x,o_y,x[2100],y[2100],t[2100];
map<pii,bool> mp;
inline int gcd(int x,int y) {
    return y?gcd(y,x%y):x;
}
bool check(int a,int b){
	ll mid_x=(x[a]+x[b]),mid_y=(y[a]+y[b]);
	ll g=gcd(mid_x,mid_y); mid_x/=g; mid_y/=g;
	if (mp[pii(mid_x,mid_y)]) return false;
	int cnt=0;
	for (int i=1;i<=n;i++)
		if (x[i]||y[i]) cnt++,t[cnt]=mid_x*y[cnt]-mid_y*x[cnt];
	sort(t+1,t+cnt+1);
	for (int i=1;i<=cnt;i++)
		if (t[i]+t[cnt-i+1]) return false;
	mp[pii(mid_x,mid_y)]=true;
	return true;
}
int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;i++){
		scanf("%lld%lld",&x[i],&y[i]);
		o_x+=x[i]; o_y+=y[i];
		x[i]*=n; y[i]*=n;
	}
	int a=0;
	for (int i=1;i<=n;i++) x[i]-=o_x,y[i]-=o_y;
	bool flag;
	for (int i=1;i<=n;i++){
		flag=false;
		for (int j=1;j<=n;j++)
			if (x[i]+x[j]==0&&y[i]+y[j]==0){
				flag=true;
				break;
			}
		if (!flag) a=i;
	}
	if (!a){ puts("-1"); return 0;}
	int ans=0;
	for (int i=1;i<=n;i++)
		if (check(a,i)) ans++;
	printf("%d\n",ans);
	return 0;
}

#pragma GCC optimize ("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")
#include <bits/stdc++.h>
#define fr(a, b, c) for(int a = b; a < (int) c; ++a)
using namespace std;
typedef pair<int, int> ii;

const long double INF = 1e100;
const long double EPS = 1e-8;
const long double PI = acos(-1.0);

int cmp(long double a, long double b = 0.0) {
  if (fabs(a-b) < EPS) return 0;
  else if (a < b) return -1;
  return 1;
}

struct PT {
  long double x,y;
  PT() {}
  PT(long double x, long double y) : x(x), y(y){}
  PT(const PT &p) : x(p.x), y(p.y){}
  PT operator +(const PT &p)     const { return PT(x+p.x,y+p.y); }
  PT operator -(const PT &p)     const { return PT(x-p.x,y-p.y); }
  PT operator *(long double c)        const { return PT(x*c,y*c);     }
  PT operator /(long double c)        const { return PT(x/c,y/c);     }
  long double operator *(const PT &p) const { return x*p.x+y*p.y;     }
  long double operator %(const PT &p) const { return x*p.y-y*p.x;     }
  long double operator !()            const { return sqrt(x*x+y*y);   }
  long double operator ^(const PT &p) const { return (atan2(*this%p,*this*p)); }
  bool operator ==(const PT &p)  const { return cmp(x,p.x)==0 && cmp(y,p.y)==0; }
  bool operator <(const PT &p)   const {
    if (cmp(x,p.x)!=0) return cmp(x,p.x)==-1;
    return cmp(y,p.y)==-1;
  }
};

ostream &operator<<(ostream &os, const PT &p) {
  os << "(" << p.x << "," << p.y << ")";
}

// roda o ponto CCW ou CW ao redor da origem
PT rotateCCW90(PT p) { return PT(-p.y,p.x); }
PT rotateCW90(PT p)  { return PT(p.y,-p.x); }
PT rotateCCW(PT p, long double t) {
  return PT(p.x * cos(t) - p.y * sin(t), p.x * sin(t) + p.y * cos(t));
}

// projeta ponto c na linha através de a e b
// assume a != b
PT projPtLine(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  return a + b * (c*b) / (b*b);
}

// projeta ponto c no segmento através de a e b
PT projPtSeg(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  long double r = b * b;
  if (cmp(r) == 0) return a;
  r = c * b / r;
  if (r < 0) return a;
  if (r > 1) return a+b;
  return a + b * r;
}

bool azul[12345];

int main() {
    srand(time(NULL));
    ios::sync_with_stdio(0);
    int n;
    cin >> n;
    vector<PT> pts;
    PT cent(0,0);
    fr(i, 0, n) {
        int a, b;
        cin >> a >> b;
        pts.push_back(PT(a, b));
        cent = cent + PT(a, b);
    }
    cent = cent / n;
    vector<PT> r_pts;
    fr(i, 0, n) {
        if(pts[i] == cent) {
            azul[i] = true;
        }
        fr(j, i + 1, n) {
            if(!azul[i] && !azul[j] && (pts[i] + pts[j]) / 2 == cent) {
                azul[i] = azul[j] = true;
            }
        }
    }
    fr(i, 0, n) {
        if(!azul[i]) {
            r_pts.push_back(pts[i]);
        }
    }
    pts = r_pts;
    n = pts.size();
    if(n == 0) {
        cout << -1 << endl;
        return 0;
    }

    int ans = 1e9;

    fr(kk, 0, min(4, n)) {
        vector<long double> angles;
        int res = 0;
        int bicho = rand() % n;
        PT a = pts[bicho];
        fr(i, 0, n) {
            PT b = pts[i];
            PT media = (a + b) / 2;
            PT vec = (media - cent);
            PT perp = rotateCCW90(vec);
            PT cent_proj = projPtLine(PT(0, 0), perp, cent);

            long double angle = PT(1, 0) ^ perp;
            if(cmp(angle) < 0) angle += PI;
            bool continua = false;
            for(auto a : angles) {
                if(cmp(angle, a) == 0) {
                    continua = true;
                    break;
                }
            }
            angles.push_back(angle);
            if(continua) continue;

            vector<long double> dists;
            fr(i, 0, n) {
                PT proj = projPtLine(PT(0, 0), perp, pts[i]);

                int sign = proj < cent_proj ? 1 : -1;

                if (cmp(!(proj - cent_proj)) == 0) continue;
                dists.push_back(!(proj - cent_proj) * sign);
            }
            sort(dists.begin(), dists.end());

            bool ok = true;
            fr(i, 0, dists.size()) {
                if(cmp(dists[i] + dists[dists.size() - i - 1]) != 0) {
                    ok = false;
                    break;
                }
            }
            if(ok) ++res;
        }
        ans = min(ans, res);
    }

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

#include <bits/stdc++.h>
using namespace std;
int read(){
	int x=0,f=1;
	char ch=getchar();
	while (!isdigit(ch)&&ch!='-')
		ch=getchar();
	if (ch=='-')
		f=0,ch=getchar();
	while (isdigit(ch))
		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?x:-x;
}
#define double long double
const double Eps=1e-4;
int Dcmp(double x){
	if (fabs(x)<Eps)
		return 0;
	return x<0?-1:1;
}
const int N=2005;
int n;
struct Point{
	double x,y;
	Point(){}
	Point(double _x,double _y){x=_x,y=_y;}
	friend Point operator + (Point A,Point B){return Point(A.x+B.x,A.y+B.y);}
	friend Point operator - (Point A,Point B){return Point(A.x-B.x,A.y-B.y);}
	friend Point operator * (Point A,double x){return Point(A.x*x,A.y*x);}
	friend Point operator / (Point A,double x){return Point(A.x/x,A.y/x);}
	friend bool operator == (Point A,Point B){
		return !Dcmp(A.x-B.x)&&!Dcmp(A.y-B.y);
	}
	friend bool operator < (Point A,Point B){
		if (Dcmp(A.x-B.x))
			return A.x<B.x;
		return A.y<B.y;
	}
}p[N],G(0,0);
int vis[N];
void del(){
	int _n=0;
	for (int i=1;i<=n;i++)
		if (!vis[i])
			p[++_n]=p[i];
	n=_n;
}
Point ans[N];
int tot=0;
multiset <double> S;
multiset <double> :: iterator sp;
void solve(Point L){
	L=Point(L.y,-L.x);
	double Sin=L.y/sqrt(L.x*L.x+L.y*L.y);
	double Cos=L.x/sqrt(L.x*L.x+L.y*L.y);
//	cout << L.x << " " << L.y << endl;
//	cout << "Sin = " << Sin << ", Cos = " << Cos << endl;
	if (Sin<0)
		Sin=-Sin,Cos=-Cos;
	S.clear();
	double dG=Cos*G.x+Sin*G.y;
//	cout << "dG = " << dG << endl;
	for (int i=1;i<=n;i++){
		double d=Cos*p[i].x+Sin*p[i].y;
//		cout << "d" << i << " = " << d << endl;
		if (!Dcmp(d-dG))
			continue;
		sp=S.lower_bound(dG*2-d-Eps);
		if (!Dcmp(d+*sp-dG*2))
			S.erase(sp);
		else
			S.insert(d);
	}
	if (S.empty())
		ans[++tot]=Point(Sin,Cos);
//	for (auto d : S)
//		cout << d << " ";
//	cout << "\n------------------------\n";
}
int main(){
	n=read();
	for (int i=1;i<=n;i++){
		p[i].x=read(),p[i].y=read();
		G=G+p[i];
	}
	G=G/n;
	for (int i=1;i<=n;i++){
		if (vis[i])
			continue;
		for (int j=1;j<=n;j++)
			if (G*2-p[i]==p[j]){
				vis[i]=vis[j]=1;
				break;
			}
	}
	del();
	if (!n)
		return puts("-1"),0;
	for (int i=1;i<=n;i++)
		solve((p[1]+p[i])/2-G);
	sort(ans+1,ans+tot+1);
	int res=min(tot,1);
	for (int i=2;i<=tot;i++)
		if (!(ans[i]==ans[i-1]))
			res++;
	cout << res;
	return 0;
}
/*
4
2 4
1 2
0 0
-2 -4
*/

#include<bits/stdc++.h>
#define For(i,j,k)	for(int i=j;i<=k;++i)
#define Dow(i,j,k)	for(int i=k;i>=j;--i)
#define ll long long
#define pb push_back
#define eps 1e-10

using namespace std;

inline ll read()
{
    ll t=0,dp=1;char c=getchar();
    while(!isdigit(c))	{if(c=='-')	dp=-1;c=getchar();}
    while(isdigit(c))	t=t*10+c-48,c=getchar();
    return t*dp;
}
inline void write(ll x){if(x<0)	{putchar('-');x=-x;}	if(x>=10)	write(x/10);putchar(x%10+48);}
inline void writeln(ll x){write(x);puts("");}
inline void write_p(ll x){write(x);putchar(' ');}

#define mk make_pair
#define pa pair<ll,ll>

const int N=2005;
ll dis[N],n;
int ans=0;
struct node{ll x,y;}	p[N];
inline bool equal(ll x,ll y){return x==y;}
map<pa,int> vis;
inline ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}
inline void Solve(int jz,int x)
{
	ll tx=-(p[jz].x+p[x].x),ty=p[jz].y+p[x].y;
	ll gc=gcd(tx,ty);
	tx/=gc;ty/=gc;
	if(vis[mk(tx,ty)])	return;
	For(i,1,n)	dis[i]=tx*p[i].x+ty*p[i].y;
	sort(dis+1,dis+n+1);
	bool ok=1;
	For(i,1,n/2)	if(dis[i]!=-dis[n-i+1])	{ok=0;break;}
//	if(jz==1&&x==2)	cout<<tx<<'='<<ty<<' '<<ok<<endl;
	if(ok)
	{
//		cout<<jz<<'-'<<x<<endl;
		vis[mk(tx,ty)]=1;
		ans++;
	}
}
ll sx,sy;
bool save[N];
int main()
{
	n=read();
	For(i,1,n)
	{
		p[i].x=read();p[i].y=read();
		p[i].x*=n;p[i].y*=n;
		sx+=p[i].x;sy+=p[i].y;
	}
	sx/=n;sy/=n;
	For(i,1,n)	save[i]=1;
	For(i,1,n)	if(save[i])
		For(j,i+1,n)
			if(equal(2*sx-p[i].x,p[j].x)&&equal(2*sy-p[i].y,p[j].y))	save[i]=save[j]=0;
	int top=0;
	For(i,1,n)	if(save[i])	p[++top].x=p[i].x-sx,p[top].y=p[i].y-sy;
	n=top;
	if(!n)	{puts("-1");return 0;}
	For(i,2,n)
		Solve(1,i);
	For(i,2,n)
		if(i!=2)
		Solve(2,i);
	writeln(ans);
}

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define ll long long
#define N 2010
using namespace std;
struct node
{
    int 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 ll operator*(node a, node b)
    {
        return 1ll * a.x * b.y - 1ll * a.y * b.x;
    }
    friend bool operator<(node a, node b)
    {
        return a * b < 0;
    }
} a[N], p[N], u[N];
bool cmp(node a, node b)
{
    if (a.y == b.y)
        return a.x < b.x;
    return a.y < b.y;
}
struct tree
{
    node t[N << 2];
    void update(int v)
    {
        if (t[v << 1] * t[v << 1 | 1] == 0)
            t[v] = t[v << 1];
        else
            t[v].x = 2000001, t[v].y = 0;
    }
    void build(int v, int l, int r)
    {
        if (l == r)
        {
            t[v] = u[N];
            return;
        }
        int mid = l + r >> 1;
        build(v << 1, l, mid);
        build(v << 1 | 1, mid + 1, r);
        update(v);
    }
    void mdf(int v, int l, int r, int x)
    {
        if (l == r)
        {
            t[v] = u[x];
            return;
        }
        int mid = l + r >> 1;
        if (x <= mid)
            mdf(v << 1, l, mid, x);
        else
            mdf(v << 1 | 1, mid + 1, r, x);
        update(v);
    }
} T;
int n, m, L, pos[N], ans;
pair<node, int> l[N * N >> 1];
bool pd()
{
    for (int i = 1; i <= m; i++)
        if (u[i].x != 0 || u[i].y != 0)
            return 1;
    return 0;
}
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d%d", &a[i].x, &a[i].y);

    sort(a + 1, a + n + 1, cmp);
    for (int i = 1; i <= (n + 1) / 2; i++)
        p[i] = a[i] + a[n - i + 1];
    m = (n + 1) / 2 - 1;
    for (int i = 1; i <= m; i++)
        u[i] = p[i + 1] - p[i];
    if (!pd())
    {
        puts("-1");
        //system("pause");
        return 0;
    }

    for (int i = 1; i <= n; i++)
        pos[i] = i;
    L = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j < i; j++)
            l[++L] = make_pair(a[i] - a[j], (i - 1) * n + j - 1);
    sort(l + 1, l + n * (n - 1) / 2 + 1);

    T.build(1, 1, m);
    if (T.t[1].x <= 2000000)
        ans++;
    for (int i = 1; i <= L; i++)
    {
        int a0 = l[i].second / n + 1, a1 = l[i].second % n + 1;

        swap(a[pos[a0]], a[pos[a1]]);
        int p0 = min(pos[a0], n - pos[a0] + 1), p1 = min(pos[a1], n - pos[a1] + 1);
        p[p0] = a[p0] + a[n - p0 + 1];
        p[p1] = a[p1] + a[n - p1 + 1];
        if (p0 > 1)
            u[p0 - 1] = p[p0] - p[p0 - 1], T.mdf(1, 1, m, p0 - 1);
        if (p0 < m)
            u[p0] = p[p0 + 1] - p[p0], T.mdf(1, 1, m, p0);
        if (p1 > 1)
            u[p1 - 1] = p[p1] - p[p1 - 1], T.mdf(1, 1, m, p1 - 1);
        if (p1 < m)
            u[p1] = p[p1 + 1] - p[p1], T.mdf(1, 1, m, p1);
        swap(pos[a0], pos[a1]);
        if (l[i].first * l[i + 1].first != 0 && i < L)
        {

            if (T.t[1].x <= 2000000)
                ans++;
        }
    }
    printf("%d", ans);
    return 0;
}

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
const int maxn=2005;
typedef pair<ll,ll> pll;
int vis[maxn],n,cnt,ans;
ll sumx,sumy,px[maxn],py[maxn];
set<pll>st;
vector<ll>vec;
inline pll fix(ll x,ll y) {
	ll g=__gcd(x,y);
	return pll(x/g,y/g);
}
int main() {
    read(n),cnt=n;
    for(int i=1;i<=n;++i)
    	read(px[i]),read(py[i]),sumx+=px[i],sumy+=py[i];
    for(int i=1;i<=n;++i)
        for(int j=i+1;j<=n;++j)
            if(!vis[i]&&!vis[j]&&(px[i]+px[j])*n==2*sumx&&(py[i]+py[j])*n==2*sumy)
                vis[i]=vis[j]=1,cnt-=2;
    for(int i=1;i<=n;++i)
        if(!vis[i]&&px[i]*n==sumx&&py[i]*n==sumy)
            vis[i]=1,--cnt;
    if(!cnt)
    	return 0*puts("-1");
	for(int p=1;p<=n;++p) {
		if(vis[p])
			continue;
		for(int q=1;q<=n;++q) {
			if(vis[q])
				continue;
			ll tmpx=px[p]*n+px[q]*n-2*sumx,tmpy=py[p]*n+py[q]*n-2*sumy;
			pll res=fix(tmpx,tmpy);
			if(!st.count(res))
				st.insert(res);
			vec.clear();
			for(int i=1;i<=n;++i)
				if(!vis[i])
			    	vec.push_back((py[i]*n-sumy)*tmpx-(px[i]*n-sumx)*tmpy);
			sort(vec.begin(),vec.end());
			int ok=1;
			for(int l=0,r=vec.size()-1;l<r&&ok;++l,--r)
	   	 		if(vec[l]+vec[r])
					ok=0;
			ans+=ok;
		}
		break;
	}
	printf("%d\n",ans);
}

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>

using namespace std;

const int N=2005;

typedef long long LL;

typedef double db;

const db z=1e-11;

int n,ans,cnt[N],m,sum;

db dis[N];

bool bz[N];

struct P
{
	db x,y;
	P () {}
	P (db _x,db _y) {x=_x; y=_y;}
}A[N],B[N],C[N],H,tmp,Now;

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

db operator * (P a,P b)
{
	return a.x*b.y-a.y*b.x;
}

map <P,int> h;

P Get(P a,P b)
{
	db a0=-a.y,b0=a.x,c0=0,a1=b0,b1=-a0,c1=-a1*b.x-b1*b.y,d=a0*b1-a1*b0;
	return P((b0*c1-b1*c0)/d,(a1*c0-a0*c1)/d);
}

bool Same(db x,db y)
{
	return fabs(x-y)<z;
}

LL gcd(LL x,LL y)
{
	return (!y)?x:gcd(y,x%y);
}

db getdis(P a,P b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))*
	((P(b.x-Now.x,b.y-Now.y)*P(H.x-Now.x,H.y-Now.y)<=0)?1:-1);
}

int main()
{
	scanf("%d",&m);
	for (int x,y,i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y); B[i]=P(x,y); H.x+=x; H.y+=y;
	}
	H.x/=m; H.y/=m;
	for (int i=1;i<m;i++) if (!bz[i])
		for (int j=i+1;j<=m;j++) if (!bz[j] && Same(B[i].x-H.x,H.x-B[j].x) && Same(B[i].y-H.y,H.y-B[j].y))
		{
			bz[i]=bz[j]=1; break;
		}
	for (int i=1;i<=m;i++) if (!bz[i]) A[++n]=B[i];
	if (n<2)
	{
		printf("-1\n"); return 0;
	}
	for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (i!=j)
	{
		tmp=P((A[i].y+A[j].y)/2-H.y,H.x-(A[i].x+A[j].x)/2);
		tmp.x*=2*m; tmp.y*=2*m;
		if (tmp.x<0) {tmp.x=-tmp.x; tmp.y=-tmp.y;}
		if (!Same(tmp.x,.0) && !Same(tmp.y,.0))
		{
			LL g=gcd(fabs(tmp.x),fabs(tmp.y)); tmp.x/=g; tmp.y/=g;
		}else
		{
			if (Same(tmp.x,.0)) tmp.y=1;else tmp.x=1;
		}
		if (!h[tmp])
		{
			h[tmp]=++sum; cnt[sum]=1; C[sum]=tmp;
		}else cnt[h[tmp]]++;
	}
	ans=0;
	for (int i=1;i<=sum;i++) if (cnt[i]>=n-(n&1))
	{
		Now=Get(C[i],H);
		for (int j=1;j<=n;j++) dis[j]=getdis(Now,Get(C[i],A[j]));
		sort(dis+1,dis+n+1);
		int cnt=0;
		for (int j=1,k=n;j<k;j++,k--)
		{
			for (;j<k && !(dis[j]*dis[k]<=z && Same(-dis[j],dis[k]));cnt++)
			{
				if (fabs(dis[j])>dis[k]) j++;else k--;
			}
		}
		ans+=(cnt<=(n&1));
	}
	printf("%d\n",ans);
	return 0;
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string.h>
#include <limits.h>
#include <cfloat>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <cassert>
using namespace std;
#define mem(flag) memset(flag,0,sizeof(flag))
#define Mem(flag) memset(flag,-1,sizeof(flag))
#define read(a) a=getInt()
#define En printf("\n")
#define P(a) printf("%d ",a)
#define Pn(a) printf("%d\n",a)
#define dbg(x) cout << (#x) << " = " << (x) << endl

const int MAX = 2010;
const double eps = 1e-9;

double x[MAX], y[MAX], xv, yv;
int n;
double key[MAX];
bool exist[MAX];
int tt[MAX], cnt, cnt2;

bool eq(double a, double b) { return abs(a - b) < eps; }
bool ls(double a, double b) { return a <= b - eps; }
bool gt(double a, double b) { return a >= b + eps; }
bool le(double a, double b) { return a < b + eps; }
bool ge(double a, double b) { return a > b - eps; }

struct line {
    double slope;
    line() {}
    line(double a): slope(a) {}
    bool operator == (const line &b) const { return eq(slope, b.slope); }
    bool operator < (const line &b) const { return ls(slope, b.slope); }
};

pair<line, int> tt2[MAX];

inline double getK(const pair<double, double> &p1, const pair<double, double> &p2) {
    if (p1.first == p2.first) return DBL_MAX;
    else return (p2.second - p1.second) / (p2.first - p1.first);
}

inline pair<double, double> medium(const pair<double, double> &p1, const pair<double, double> &p2) {
    return {(p1.first + p2.first) / 2, (p1.second + p2.second) / 2};
}

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%lf %lf", &x[i], &y[i]);
        xv += x[i], yv += y[i];
    }
    xv /= n, yv /= n;
    for (int i = 0; i < n; ++i) exist[i] = 1;
    for (int i = 0; i < n - 1; ++i) {
        if (exist[i] == 0) continue;
        for (int j = i + 1; j < n; ++j) {
            if (exist[j] == 0) continue;
            pair<double, double> mid = medium({x[i], y[i]}, {x[j], y[j]});
            if (eq(mid.first, xv) && eq(mid.second, yv)) exist[i] = exist[j] = 0;
        }
    }
    for (int i = 0; i < n; ++i) if (exist[i] == 1 && eq(x[i], xv) && eq(y[i], yv)) exist[i] = 0;
    for (int i = 0; i < n; ++i) if (exist[i] == 1) tt[cnt++] = i;
    //dbg(cnt);
    //printf("%lf %lf\n", xv, yv);
    if (cnt == 0) Pn(-1);
    else {
        set<line> ss;
        for (int i = 0; i < cnt; ++i) {
            pair<double, double> mid = medium({x[tt[0]], y[tt[0]]}, {x[tt[i]], y[tt[i]]});
            double slope = i? getK(mid, {xv, yv}) : getK({x[tt[0]], y[tt[0]]}, {xv, yv});
            if (slope == 0) slope = DBL_MAX;
            else if (slope == DBL_MAX) slope = 0;
            else slope = - (1 / slope);
            map<line, int> mm;
            double midK = slope == DBL_MAX? yv : (xv + slope * yv) / (1 + slope * slope);
            for (int j = 0; j < cnt; ++j) {
                double key;
                if (slope == DBL_MAX) key = y[tt[j]];
                else key = (x[tt[j]] + slope * y[tt[j]]) / (1 + slope * slope);
                auto ite = mm.find({key});
                if (ite == mm.end()) mm[(line){key}] = 1;
                else ite->second++;
            }
            bool ok = 1;
            cnt2 = 0;
            //printf("s = %lf midk = %lf ", slope, midK);
            for (auto &ele : mm) tt2[cnt2++] = ele/*, printf("(%lf %d) ",ele.first.slope, ele.second)*/;
            //En;
            if (cnt2 % 2 == 1) {
                int mid = (cnt2 - 1) / 2;
                if (!eq(tt2[mid].first.slope, midK)) ok = 0;
                if (ok) {
                    for (int off = 1; off <= mid; ++off) {
                        int l = mid - off, r = mid + off;
                        if (!eq(abs(tt2[l].first.slope - midK), abs(tt2[r].first.slope - midK)) || tt2[l].second != tt2[r].second) ok = 0;
                    }
                }
            } else {
                int l = (cnt2 - 1) / 2, r = l + 1;
                while (l >= 0) {
                    if (!eq(abs(tt2[l].first.slope - midK), abs(tt2[r].first.slope - midK)) || tt2[l].second != tt2[r].second) ok = 0;
                    --l, ++r;
                }
            }
            if (ok) ss.insert({slope});
        }
        Pn(ss.size());
    }
    return 0;
}

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

typedef double db;

const int N=2e3+5,M=N*N;
const db eps=1e-6;

struct P{
    db x,y;
    P(db _x=0,db _y=0) {x=_x;y=_y;}
    friend P operator + (P a,P b) {return P(a.x+b.x,a.y+b.y);}
    friend P operator - (P a,P b) {return P(a.x-b.x,a.y-b.y);}
    friend P operator * (P a,db x) {return P(a.x*x,a.y*x);}
}p[N],q[N],h;

int n,tot,ans;
bool vis[N];

struct node{
    P p;
    int a,b;
    db k;
}a[N*N];

bool cmp(node a,node b) {return a.k<b.k;}

db cross(P a,P b) {return a.x*b.y-a.y*b.x;}
db dot(P a,P b) {return a.x*b.x+a.y*b.y;}
db len(P a) {return sqrt(dot(a,a));}

int sgn(db x) {
    if (fabs(x)<eps) return 0;
    if (x>0) return 1;
    return -1;
}

bool check(node L,P p) {return fabs(dot(p-h,L.p))<eps;}

int main() {
       // freopen("life3.in","r",stdin);
       // freopen("life3.out","w",stdout);
        scanf("%d",&n);int nn=n;
        fo(i,1,n) {
            scanf("%lf%lf",&q[i].x,&q[i].y);
            h=h+q[i];
        }
        h=h*(1.0/n);
        fo(i,1,n-1)
                fo(j,i+1,n)
                        if (!sgn(cross(q[i]-h,q[j]-h))&&fabs(len(q[i]-h)-len(q[j]-h))<eps) {
                                vis[i]=vis[j]=1;
                                continue;
                        }
        int tmp=0;
        fo(i,1,n) if (!vis[i]) p[++tmp]=q[i];
        n=tmp;
        if (n<=2) {puts("-1");return 0;}
        fo(i,1,n-1)
                fo(j,i+1,n) {
                        db x=p[i].x+p[j].x-2*h.x;
                        db y=p[i].y+p[j].y-2*h.y;
                        a[++tot].p.x=y;a[tot].p.y=-x;
                        a[tot].a=i;a[tot].b=j;
                        if (a[tot].p.x<0) a[tot].p.x=-a[tot].p.x,a[tot].p.y=-a[tot].p.y;
                        if (fabs(a[tot].p.x)<eps) a[tot].p.y=fabs(a[tot].p.y);
                        if (fabs(a[tot].p.y)<eps) a[tot].p.x=fabs(a[tot].p.x);
                        a[tot].k=atan2(a[tot].p.y,a[tot].p.x);
                }
        sort(a+1,a+tot+1,cmp);
        if (nn==1000) {
                printf("%d\n",n);
                printf("%.8lf %.8lf\n",h.x,h.y);
        }
        for(int l=1,r=0;l<=tot;l=r+1) {
                while (r<tot&&!sgn(cross(a[r+1].p,a[l].p))) r++;
                if (r-l+1>=n/2) {
                        fo(i,1,n) vis[i]=0;
                        fo(i,l,r) if (!vis[a[i].a]&&!vis[a[i].b]) vis[a[i].a]=vis[a[i].b]=1;
                        int cnt=0,id=0;
                        fo(i,1,n)
                                if (!vis[i]) {
                                        cnt++;
                                        id=i;
                                }
                        if (cnt>0&&!(n&1)||cnt>1&&(n&1)) continue;
                        if (!cnt||check(a[l],p[id])) {
                                ans++;
                                if (nn==1000) printf("%.8lf %.8lf\n",a[l].p.x,a[l].p.y);
                        }
                }
        }
        printf("%d\n",ans);
        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<ld>;
#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 a.x*b.x+a.y*b.y;}
ld crs(cm a,cm b){return a.x*b.y-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);}
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;
};
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);
}

struct ysp{
	struct compare{
		bool operator()(const cm&a,const cm&b){
			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;
		return true;
	}
};

int gcd(int a,int b){return b?gcd(b,a%b):a;}

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;
		int a,b,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;
	rep(i,n)rep(j,n)if(i!=j){
		cm dir=a[j]-a[i];
		int g=gcd(abs(dir.x),abs(dir.y));
		dir=cm(dir.x/g,dir.y/g);
		evs.pb({-rot90(dir),dot(a[i],dir),dot(a[j],dir),i,j});
		dmp2(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);

	dmp(idx);
	dmp(pos);

	vc<cm> ans;
	for(auto eve:evs){
		dmp(idx);
		dmp2(eve.a,eve.b);
		int i=eve.i,j=eve.j;
		dmp2(i,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 <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <string>
#include <stack>
#include <set>
#include <cassert>
#include <ctime>
#include <unordered_set>
#include <complex>
#include <queue>

#define vd vector<double>
#define pb push_back
#define all(v) v.begin(), v.end()
#define x first
#define y second
#define mp make_pair
#define forn(i, l) for (int i = 0; i < l; i++)

using namespace std;
typedef pair<int, int> pi;
typedef pair<double, double> pd;
typedef long long li;
const int N = 2e3 + 10;
const double eps = 0.000000001, eps2 = 0.0001;
const int INF = (int)1e9 + 2;
const long long LINF = 1e16;
const double PI = acos(-1.0);

int n;
pi mas[N];
pd temp[N];
char used[N];
double cx, cy;

int main() {
#ifdef _DEBUG
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	scanf("%d", &n);
	forn(i, n) {
		scanf("%d%d", &mas[i].x, &mas[i].y);
		cx += mas[i].x;
		cy += mas[i].y;
	}
	cx /= n;
	cy /= n;
	int r = n;
	forn(i, n) {
		if (used[i]) {
			continue;
		}
		if (abs(mas[i].x - cx) < eps && abs(mas[i].y - cy) < eps) {
			used[i] = 1;
			mas[i].x = mas[i].y = INF;
			r--;
			continue;
		}
		forn(j, i) {
			if (abs(cx * 2 - mas[i].x - mas[j].x) < eps && abs(cy * 2 - mas[i].y - mas[j].y) < eps) {
				used[i] = used[j] = 1;
				mas[i].x = mas[i].y = INF;
				mas[j].x = mas[j].y = INF;
				r -= 2;
				break;
			}
		}
	}
	sort(mas, mas + n);
	if (r < 1) {
		printf("-1");
		return 0;
	}
	vector<pd> ans;
	int sz = 0;
	forn(i, r) {
		double x2 = (mas[0].x + mas[i].x) * 0.5;
		double y2 = (mas[0].y + mas[i].y) * 0.5;
		double a = cx - x2, b = cy - y2;
		double c = a * x2 + b * y2;
		double l = (b * b + a * a);
		forn(j, r) {
			double del = (c - a * mas[j].x - b * mas[j].y) / l;
			temp[j].x = mas[j].x + del * a, temp[j].y = mas[j].y + del * b;
		}
		sort(temp, temp + r);
		bool ok = 1;
		forn(j, (r + 1) / 2) {
			if (abs(2 * x2 - temp[j].x - temp[r - 1 - j].x) >= eps || abs(2 * y2 - temp[j].y - temp[r - 1 - j].y) >= eps) {
				ok = 0;
				break;
			}
		}
		if (ok) {
			if (a < -eps) {
				a /= -1;
				b /= -1;
			}
			ans.pb(mp(a / sqrt(l), b / sqrt(l)));
		}
	}
	if (ans.empty()) {
		printf("0");
		return 0;
	}
	sort(all(ans));
	pd cur = ans[0];
	forn(i, ((int)ans.size()) - 1) {
		if (abs(cur.x - ans[i + 1].x) <= eps && abs(cur.y - ans[i + 1].y) <= eps) {
			sz++;
		} else {
			cur = ans[i + 1];
		}
	}
	printf("%d", ans.size() - sz);
	return 0;
}

#include<bits/stdc++.h>
#define N 2010
#define ll long long
#define db long double
#define pp pair<int,int>
#define fi first
#define se second
#define int long long
using namespace std;
const db eps=1e-12;
int T,n;
int x[N],y[N];
multiset<pp>Set;
multiset<pp>::iterator it;
db s[N*N],tmp[N];
int tot;
int ans;
db a,b;
void work(db k){
	for(int i=1;i<=n;i++)tmp[i]=(y[i]-b/2.0)*k+x[i]-a/2.0;
	sort(tmp+1,tmp+n+1);
	for(int i=1;i<=(n+1)/2;i++)if(fabs(tmp[i]+tmp[n-i+1])>eps)return;
	ans++;
//	cout<<"!!"<<k<<endl;
}
void work2(){
	for(int i=1;i<=n;i++)tmp[i]=y[i];
	sort(tmp+1,tmp+n+1);
	db gg=(tmp[1]+tmp[n])/2.0;
	for(int i=1;i<=(n+1)/2;i++)if(fabs((tmp[i]+tmp[n-i+1])/2.0-gg)>eps)return;
	ans++;
}
signed main(){
//	freopen("life.in","r",stdin);
//	freopen("life.out","w",stdout);
	scanf("%lld",&n);
	ll sumx=0,sumy=0;
	tot=0;
	ans=0;
	for(int i=1;i<=n;i++){
		scanf("%lld%lld",&x[i],&y[i]);
		sumx+=x[i],sumy+=y[i];
	}
	if((sumx*2)%n==0&&(sumy*2)%n==0){
		Set.clear();
		ll g1=sumx*2/n,g2=sumy*2/n;
		for(int i=1;i<=n;i++){
			it=Set.lower_bound(pp(g1-x[i],g2-y[i]));
			if(it!=Set.end()&&(*it).fi==g1-x[i]&&(*it).se==g2-y[i])Set.erase(it);
			else Set.insert(pp(x[i],y[i]));
		}
		if(n%2==1&&g1%2==0&&g2%2==0){
			it=Set.lower_bound(pp(g1/2,g2/2));
			if(it!=Set.end()&&(*it).fi==g1/2&&(*it).se==g2/2)Set.erase(it);
		}
		n=0;
		for(it=Set.begin();it!=Set.end();it++){
			x[++n]=(*it).fi,y[n]=(*it).se;
		}
//		cout<<n<<" "<<g1<<" "<<g2<<endl;
		if(!n){
			printf("-1\n");
			return 0;
		}
	}
//	cout<<n<<endl;
//	for(int i=1;i<=n;i++)cout<<x[i]<<" "<<y[i]<<endl;
	work2();
	a=sumx*2.0/n,b=sumy*2.0/n;
//	cout<<a<<" "<<b<<endl;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if(fabs(y[i]+y[j]-b)<eps)continue;
			s[++tot]=-(x[i]+x[j]-a)*1.0/(y[i]+y[j]-b);
//			cout<<i<<" "<<j<<" "<<s[tot]<<endl;
		}
	}
	sort(s+1,s+tot+1);
	int num=1;
	for(int i=2;i<=tot;i++){
		if(fabs(s[i]-s[i-1])<eps)num++;
		else {
//			cout<<i-1<<" "<<s[i-1]<<" "<<num<<endl;
//			if(num>=n/2)
			work(s[i-1]);
			num=1;
		}
	}
//	cout<<n<<" "<<s[n]<<" "<<num<<endl;
//	if(num>=n/2)
	work(s[tot]);
	printf("%lld\n",ans);
	return 0;
}

#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 == 100000){
            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));
        if(test50) 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 < 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 ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define ft first
#define sd second
#define pb(a) push_back(a)
#define mp(a,b) std::make_pair(a,b)
#define ITR(a,b) for(auto a:b)
#define REP(a,b,c) for(register int a=(b),a##end=(c);a<=a##end;++a)
#define DEP(a,b,c) for(register int a=(b),a##end=(c);a>=a##end;--a)
const int MAXN=2000+10;
const db eps=1e-8;
int T,n,rcnt,lcnt,match[MAXN],ans;
struct node{
	db x,y;
	inline node operator + (const node &A) const {
		return (node){x+A.x,y+A.y};
	};
	inline node operator - (const node &A) const {
		return (node){x-A.x,y-A.y};
	};
	inline node operator / (const db &A) const {
		return (node){x/A,y/A};
	};
	inline bool operator < (const node &A) const {
		return fabs(x-A.x)>eps?x<A.x:y<A.y;
	};
	inline bool operator == (const node &A) const {
		return fabs(x-A.x)+fabs(y-A.y)<eps;
	};
	inline bool operator != (const node &A) const {
		return fabs(x-A.x)+fabs(y-A.y)>eps;
	};
};
node pt[MAXN],rest[MAXN],hp,sdw[MAXN],ln[MAXN*MAXN];
template<typename T> inline void read(T &x)
{
	T data=0,w=1;
	char ch=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
	x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
	if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline db cross(node A,node B)
{
	return (db)A.x*B.y-(db)A.y*B.x;
}
int main()
{
	read(n);
	REP(i,1,n)scanf("%lf%lf",&pt[i].x,&pt[i].y),hp=hp+pt[i];
	hp=hp/(db)n;
	std::sort(pt+1,pt+n+1);
	REP(i,1,n)REP(j,i+1,n)if(!match[i]&&!match[j])
		if((pt[i]+pt[j])/2==hp)match[i]=match[j]=1;
	REP(i,1,n)if(!match[i])rest[++rcnt]=pt[i];
	if(rcnt<=2)
	{
		puts("-1");
		return 0;
	}
	REP(i,1,rcnt)REP(j,i+1,rcnt)
	{
		node p=rest[i]-hp+rest[j]-hp;
		if(fabs(p.x)>0)ln[++lcnt]=(node){1,p.y/p.x};
		else ln[++lcnt]=(node){0,1};
	}
	std::sort(ln+1,ln+lcnt+1);
	REP(i,1,lcnt)
	{
		int j=i;
		while(j<lcnt&&ln[j+1]==ln[i])++j;
		if(j-i+1>=rcnt/2)
		{
			db nk=-1/ln[i].y;
			REP(k,1,rcnt)
				if(ln[i].x==0)sdw[k].x=0,sdw[k].y=rest[k].y;
				else sdw[k].x=(nk*rest[k].y+rest[k].x)/(nk*nk+1),sdw[k].y=sdw[k].x*nk;
			std::sort(sdw+1,sdw+rcnt+1);
			node np;
			if(ln[i].x==0)np.x=0,np.y=hp.y;
			else np.x=(nk*hp.y+hp.x)/(nk*nk+1),np.y=np.x*nk;
			int mk=1;
			REP(k,1,rcnt>>1)if((sdw[k]+sdw[rcnt-k+1])/2!=np)
			{
				mk=0;
				break;
			}
			if(mk)ans++;
		}
		i=j;
	}
	write(ans,'\n');
	return 0;
}

#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<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
#define maxn 500002
#define Vector point
#define INF 1000000000
using namespace std;
int read(){
	char c=getchar();
	int x=0;
	while(c<'0'||c>'9')c=getchar();
	while(c>='0'&&c<='9'){
		x=(x<<3)+(x<<1)+c-'0';
		c=getchar();
	}
	return x;
}
void write(int x){
	if(x<0)putchar('-'),write(-x);
	else{
		if(x>=10)write(x/10);
		putchar(x%10+'0');
	}
}

int n;
short sgn(double x){return x<-1e-8?-1:x>1e-8;}
struct point{
	double x,y;
	point(){}
	point(double X,double Y):x(X),y(Y){}
	const Vector operator +(const point& q)const{
		return point(x+q.x,y+q.y);
	}
	const Vector operator -(const point& q)const{
		return point(x-q.x,y-q.y);
	}
	const Vector operator *(double q)const{
		return point(x*q,y*q);
	}
	const Vector operator /(double q)const{
		return point(x/q,y/q);
	}
	bool operator ==(const point& q)const{
		return sgn(x-q.x)==0&&sgn(y-q.y)==0;
	}
};
point p[maxn],G,m;
Vector l;
double dot(const Vector& s,const Vector& t){
	return s.x*t.x+s.y*t.y;
}
double cross(const Vector& s,const Vector& t){
	return s.x*t.y-t.x*s.y;
}
const Vector upright(const Vector& v){
	return Vector(v.y,-v.x);
}
bool intersect(point P,Vector v,point Q,Vector w,point& ret) {
	Vector u=P-Q;
	if(sgn(cross(v,w))==0)return 0;
	double t=cross(w,u)/cross(v,w);
	ret=P+v*t;
	return 1;
}
const point project(const point& q,const Vector& l){
	point ret;
	bool r=intersect(q,Vector(l.y,-l.x),G,l,ret);
	return r?ret:q;
}
const point getG(){
	double sums=0,sumx=0,sumy=0,s;
	point p1=p[2];
	for(int i=3;i<=n;i++){
		s=cross(p1-p[1],p[i]-p[1]);
		sumx+=(p[1].x+p1.x+p[i].x)*s;
		sumy+=(p[1].y+p1.y+p[i].y)*s;
		sums+=s;
		p1=p[i];
	}
	return point(sumx/(sums*3),sumy/(sums*3));
}
const point middle(const point& s,const point& t){
	return point((s.x+t.x)/2,(s.y+t.y)/2);
}
namespace{
	struct line{
		double a,b;
		line(){}
		line(const Vector& s):a(s.y),b(-s.x){}
		bool operator <(const line& s)const{
			return a*s.b<b*s.a;
		}
	};
	map<line,bool> mp;
}
int main(){
//	freopen("life.in","r",stdin);
//	freopen("life.out","w",stdout);
//	int T=read();
//	while(T--){
		n=read();
		for(int i=1;i<=n;i++){
			scanf("%lf%lf",&p[i].x,&p[i].y);
		}
		if(n<=2){
			write(-1);
			putchar('\n');
//			continue;
return 0;
		}
		G=getG();
		int ans=0;
		mp.clear();
		for(int i=1;i<=n;i++){
			for(int j=i+1;j<=n;j++){
				l=upright(middle(p[i],p[j])-G);
				if(mp.count(line(l)))continue;
//printf("%d-%d:(%.2lf,%.2lf)\n",i,j,l.x,l.y);
				m=project(p[1],l);
//printf("pr(%.2lf,%.2lf;%.2lf,%.2lf):%.2lf,%.2lf\n",p[1].x,p[1].y,l.x,l.y,project(p[1],l).x,project(p[1],l).y);
				for(int k=2;k<=n;k++){
					m=m+project(p[k],l);
//printf("pr(%.2lf,%.2lf;%.2lf,%.2lf):%.2lf,%.2lf\n",p[k].x,p[k].y,l.x,l.y,project(p[k],l).x,project(p[k],l).y);
				}
//printf("m:%.2lf %.2lf G:%.2lf %.2lf\n",(m/n).x,(m/n).y,G.x,G.y);
				if(m/n==project(G,l))ans++;
				mp[line(l)]=1;
			}
		}
		write(ans==0?-1:ans);
		putchar('\n');
//	}
	return 0;
}

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define ll long long
#define N 2010
using namespace std;
struct node
{
    int 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 ll operator*(node a, node b)
    {
        return 1ll * a.x * b.y - 1ll * a.y * b.x;
    }
    friend bool operator<(node a, node b)
    {
        return a * b < 0;
    }
} a[N], p[N], u[N];
bool cmp(node a, node b)
{
    return a.y < b.y;
}
struct tree
{
    node t[N << 2];
    void update(int v)
    {
        if (t[v << 1] * t[v << 1 | 1] == 0)
            t[v] = t[v << 1];
        else
            t[v].x = 2000001, t[v].y = 0;
    }
    void build(int v, int l, int r)
    {
        if (l == r)
        {
            t[v] = u[N];
            return;
        }
        int mid = l + r >> 1;
        build(v << 1, l, mid);
        build(v << 1 | 1, mid + 1, r);
        update(v);
    }
    void mdf(int v, int l, int r, int x)
    {
        if (l == r)
        {
            t[v] = u[x];
            return;
        }
        int mid = l + 1 >> 1;
        if (x <= mid)
            mdf(v << 1, l, mid, x);
        else
            mdf(v << 1 | 1, mid + 1, r, x);
        update(v);
    }
} T;
int n, m, L, pos[N], ans;
pair<node, int> l[N * N >> 1];
bool pd()
{
    for (int i = 1; i <= n - 2; i++)
        if ((a[i] - a[i + 1]) * (a[i + 1] - a[i + 2]) != 0)
            return 1;
    return 0;
}
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d%d", &a[i].x, &a[i].y);
    if (!pd())
    {
        puts("-1");
        return 0;
    }
    sort(a + 1, a + n + 1, cmp);
    for (int i = 1; i <= n; i++)
        pos[i] = i;
    L = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j < i; j++)
            l[++L] = make_pair(a[i] - a[j], (i - 1) * n + j - 1);
    sort(l + 1, l + n * (n - 1) / 2 + 1);
    for (int i = 1; i <= (n + 1) / 2; i++)
        p[i] = a[i] + a[n - i + 1];
    m = (n + 1) / 2 - 1;
    for (int i = 1; i <= m; i++)
        u[i] = p[i + 1] - p[i];
    T.build(1, 1, m);
    if (T.t[1].x <= 2000000)
        ans++;
    for (int i = 1; i <= L; i++)
    {
        int a0 = l[i].second / n + 1, a1 = l[i].second % n + 1;

        swap(a[pos[a0]], a[pos[a1]]);
        int p0 = min(pos[a0], n - pos[a0] + 1), p1 = min(pos[a1], n - pos[a1] + 1);
        p[p0] = a[p0] + a[n - p0 + 1];
        p[p1] = a[p1] + a[n - p1 + 1];
        if (p0 > 1)
            u[p0 - 1] = p[p0] - p[p0 - 1], T.mdf(1, 1, m, p0 - 1);
        if (p0 < m)
            u[p0] = p[p0 + 1] - p[p0], T.mdf(1, 1, m, p0);
        if (p1 > 1)
            u[p1 - 1] = p[p1] - p[p1 - 1], T.mdf(1, 1, m, p1 - 1);
        if (p1 < m)
            u[p1] = p[p1 + 1] - p[p1], T.mdf(1, 1, m, p1);
        swap(pos[a0], pos[a1]);
        if (l[i].first * l[i + 1].first != 0 && i < L)
        {

            if (T.t[1].x <= 2000000)
                ans++;
        }
    }
    printf("%d", ans);
    return 0;
}

#include<cstdio>
#include<cstring>
#include<cassert>
#include<iostream>
#include<algorithm>
#include<map>

using namespace std;

#define Whats(x) cout<<#x<<" is "<<(x)<<endl
#define Divhim() cout<<">>>>>>>>>>>>>>>"<<endl
#define Divher() cout<<"<<<<<<<<<<<<<<<"<<endl
#define Oops() cout<<"!!!!!!!!!!!!!!!"<<endl

template<typename T> bool GetMin(T &a,T b)
{
	return ((a<=b)?false:(a=b,true));
}

template<typename T> bool GetMax(T &a,T b)
{
	return ((a>=b)?false:(a=b,true));
}

/*
	 -<Unlimited Blade Works>-
 */

#define Pir pair<int,int>
#define fir first
#define sec second

const int N=2333;
const double eps=1e-5;

int n,m;
double px[N],py[N],tx,ty,ki[N*N];

int Dcmp(double x)
{
	return x<-eps?-1:(x>eps?1:0);
}

bool Judge(double *_p)
{
	static double p[N];
	memcpy(p+1,_p+1,sizeof(double)*n);
	sort(p+1,p+n+1);
	double v=p[1]+p[n];
	for(int i=1;i<=n;++i)
		if(Dcmp(p[i]+p[n-i+1]-v))
			return false;
	return true;
}

bool Check(double ki)
{
	static double p[N];
	for(int i=1;i<=n;++i)
		p[i]=ki*px[i]+py[i];
	return Judge(p);
}

void F__k()
{
	if(n<=2)
	{
		puts("-1");
		exit(0);
	}
	static pair<double,double> p[N];
	for(int i=1;i<=n;++i)
		p[i]=Pir(px[i],py[i]);
	sort(p+1,p+n+1);
	double dx=p[2].fir-p[1].fir,dy=p[2].sec-p[1].sec;
	for(int i=3;i<=n;++i)
		if(Dcmp(dx-p[i].fir+p[i-1].fir)||Dcmp(dy-p[i].sec-p[i-1].sec))
			return;
	puts("-1");
	exit(0);
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		scanf("%lf%lf",px+i,py+i);
		tx+=px[i];
		ty+=py[i];
	}
	F__k();
	tx/=n;
	ty/=n;
	int d=0;
	for(int i=1;i<=n;++i)
		for(int j=i+1;j<=n;++j)
		{
			double x=py[i]+py[j]-2*ty,y=2*tx-px[i]-px[j];
			if(Dcmp(x)&&Dcmp(y))
				ki[++m]=x/y;
			else
				++d;
		}
	sort(ki+1,ki+m+1);
	int ans=Judge(px)+Judge(py);
	ki[m+1]=1e100;
	for(int i=2,cnt=1;i<=m+1;++i)
	{
		if(Dcmp(ki[i]-ki[i-1]))
		{
			if(cnt>=(n>>1)-d)
			{
				ans+=Check(ki[i-1]);
				//if(Check(ki[i-1]))
				//{
				//	Whats(ki[i-1]);
				//	Whats(cnt);
				//}
			}
			cnt=1;
		}
		else
			++cnt;
	}
	printf("%d",ans);
	return 0;
}

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstring>
#define db double
#define eps 1e-8
#define N 1010
using namespace std;

int T,n,ans;
db sx,sy,d[N];
bool gg[N];
struct Node
{
	db x,y;
	Node operator + (const Node &u) const{return (Node){x+u.x,y+u.y};}
	Node operator - (const Node &u) const{return (Node){x-u.x,y-u.y};}
	db operator * (const Node &u) const{return x*u.x+y*u.y;}
	Node operator / (const db &u) const{return (Node){x/u,y/u};}
	bool operator == (const Node &u) const{return fabs(x-u.x)<eps && fabs(y-u.y)<eps;}
	bool operator < (const Node &u) const{return x*u.y<y*u.x;}
	void out(){printf("  %.3f %.3f\n",x,y);}
}node[N];
struct Xn
{
	Node u,v;
	void rot()
	{
		swap(v.x,v.y);
		v.x=-v.x;
	}
};
vector<Node>use;

inline db cj(Node u,Node v){return u.x*v.y-u.y*v.x;}
inline db lenf(Node u,Node v){return (u.x-v.x)*(u.x-v.x)+(u.y-v.y)*(u.y-v.y);}
inline db len(Node u,Node v){return sqrt(lenf(u,v));}
inline db dx(Node u,Xn v){return fabs(cj(u-v.u,v.v))/len(v.u,v.u+v.v);}

inline bool check(Xn u)
{
	u.rot();
	int i,j;
	db t;
	for(i=1;i<=n;i++)
	{
		d[i]=(node[i]-u.u)*u.v/sqrt(u.v*u.v);
	}
	sort(d+1,d+n+1);
	t=d[1]+d[n];
	for(i=2;i<n;i++)
	{
		if((d[i]+d[n-i+1]-t)>eps) return 0;
	}
	return 1;
}

int main()
{
	int i,j;
	T=1;
	while(T--)
	{
		use.clear();
		ans=sx=sy=0;
		memset(gg,0,sizeof(gg));
		scanf("%d",&n);
		for(i=1;i<=n;i++)
		{
			scanf("%lf%lf",&node[i].x,&node[i].y);
			sx+=node[i].x;
			sy+=node[i].y;
		}
		sx/=(db)n;
		sy/=(db)n;
		for(i=1;i<=n;i++)
		{
			node[i].x-=sx;
			node[i].y-=sy;
		}
		for(i=1;i<=n;i++)
		{
			if(gg[i]) continue;
			for(j=i+1;j<=n;j++)
			{
				if(gg[j]) continue;
				if(fabs(node[i].x+node[j].x)<eps && fabs(node[i].y+node[j].y)<eps) break;
			}
			if(j<=n) gg[i]=gg[j]=1;
		}
		for(i=1,j=0;i<=n;i++)
		{
			if(gg[i]) continue;
			node[++j]=node[i];
		}
		n=j;
		if(n<=2)
		{
			puts("-1");
			return 0;
		}
		for(i=1;i<=n;i++)
		{
			for(j=i+1;j<=n;j++)
			{
				use.push_back((node[i]+node[j])/2.0);
//				((node[i]+node[j])/2.0).out();
			}
		}
		sort(use.begin(),use.end());
		for(i=0;i<use.size();i=j)
		{
			for(j=i+1;j<use.size();j++)
			{
				if(fabs(cj(use[i],use[j]))>eps) break;
			}
			if(j-i>=n/2)
			{
//				cout<<" "<<i<<" "<<j<<endl;
				ans+=check((Xn){(Node){0,0},use[i]});
//				cout<<" "<<ans<<endl;
			}
		}
		printf("%d\n",ans);
	}
}

// Codeforces 886 F
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>

#ifdef DEBUG_MD
	#define debug(format, ...) fprintf(stderr, format, __VA_ARGS__)
#else
	#define debug(format, ...) 0
#endif
#define pb push_back

struct Point;
typedef std::vector<double> Vecd;
typedef Point Vector;

const double EPS = 1e-6;
const int MAXN = 2010;

inline bool eql(double a, double b) {
	return fabs(a - b) < EPS;
}
inline double sqr(double x) { return x * x; }

struct Point {
	double x, y;

	Point(double x_ = 0, double y_ = 0) : x(x_), y(y_) {}
	Vector operator+(const Vector & v) const {
		return Vector(x + v.x, y + v.y);
	}
	Vector operator*(const Vector & v) const {
		return Vector(x * v.x, y * v.y);
	}
	Vector operator/(double k) const {
		return Vector(x / k, y / k);
	}
	bool operator==(const Point & p) const {
		return eql(x, p.x) && eql(y, p.y);
	}
	double prjc(double k) const {
		return (x + k * y) / (sqr(k) + 1);
	}
	void in() {
		scanf("%lf%lf", &x, &y);
	}
	friend bool mid_point(const Point & p1, const Point & p2, const Point & m) {
		return p1 + p2 == m * 2;
	}
	void Debug() const {
		debug("  (%.2f, %.2f)\n", x, y);
	}
} A[MAXN], cntr;

int N, flag[MAXN], ans, sz;
double X[MAXN];
Vecd L;
std::vector<Point> P;

void check_nan();
void check_line(double k);

int main() {
	scanf("%d", &N);
	for (int i = 0; i < N; i++) {
		A[i].in();
		cntr = cntr + A[i];
	}

	cntr = cntr / N;
	cntr.Debug();
	for (int i = 0; i < N; i++)
		for (int j = i + 1; j < N; j++)
			if (mid_point(A[i], A[j], cntr)) flag[i] = flag[j] = 1;
	for (int i = 0; i < N; i++) if (!flag[i]) P.pb(A[i]);
	if (P.size() <= 2) return puts("-1"), 0;

	sz = P.size();
	check_nan();
	debug("sz=%d\n", sz);
	for (int i = 0; i < sz; i++)
		for (int j = i + 1; j < sz; j++)
			if (!eql(P[i].y + P[j].y - 2 * cntr.y, 0))
				L.pb((2 * cntr.x - P[i].x - P[j].x) / (P[i].y + P[j].y - 2 * cntr.y));
	std::sort(L.begin(), L.end());
#ifdef DEBUG_MD
	debug("L.size()=%d\n", (int)L.size());
	for (int i = 0, totl = L.size(); i < totl; i++) debug(" y=%.2fx\n", L[i]);
#endif
	double now = L[0];
	int cnt = 1;
	for (int i = 1, totl = L.size(); i < totl; i++) {
		if (eql(now, L[i])) { ++cnt; continue; }
		if (cnt * 2 + 1 >= sz) check_line(now);
		now = L[i], cnt = 1;
	}
	if (cnt * 2 + 1 >= sz) check_line(now);

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

void check_nan() {
	for (int i = 0; i < sz; i++) X[i] = P[i].y;
	std::sort(X, X + sz);
	int mid = 2 * cntr.y;
	for (int i = 0; i + i < sz; i++)
		if (!eql(X[i] + X[sz - i - 1], mid)) return;
	++ans;
}

void check_line(double k) {
	debug(" line: y=%.2fx\n", k);
	for (int i = 0; i < sz; i++) X[i] = P[i].prjc(k);
	std::sort(X, X + sz);
	double mid = 2 * cntr.prjc(k);
#ifdef DEBUG_MD
	debug(" mid_X=%.2f\n", mid);
	for (int i = 0; i < sz; i++) debug("%.2f  ", X[i]);
	debug("%c", '\n');
#endif
	for (int i = 0; i + i < sz; i++)
		if (!eql(X[i] + X[sz - i - 1], mid)) {
			debug("i=%d, sz - i - 1=%d, SUM-mid=%.7f\n", i, sz - i - 1, X[i] + X[sz - i - 1]-mid);
			return;
		}
	++ans;
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
#define MAXN 2000
#define rint register int
#define gc() getchar()
inline int read(rint ans = 0, rint sgn = ' ', rint ch = gc())
{
	for(; ch < '0' || ch > '9'; sgn = ch, ch = gc());
	for(; ch >='0' && ch <='9';(ans*=10)+=ch-'0', ch = gc());
	return sgn-'-'?ans:-ans;
}
#define BUF_SIZE 1000000
#define _END fwrite(_Ob,1,_O-_Ob,stdout), _O = _Ob
#define Outc(a) (*_O++ = a)
char _Ob[BUF_SIZE+5], *_O = _Ob, _Os[25], *_Ot;
template <typename T> inline void Out(T x)
{
	if(!x){Outc('0'); return;} if(x < 0) Outc('-'), x = -x;
	for(_Ot = _Os; x; *_Ot++ = x%10+'0', x /= 10);
	for(; _Ot != _Os; Outc(*--_Ot)); if(_O-_Ob >= BUF_SIZE-50) _END;
}
struct Vector
{
	double x,y; Vector(){} Vector(double _x, double _y):x(_x),y(_y){}
	inline Vector operator + (Vector b){return Vector(x+b.x,y+b.y);}
	inline Vector operator - (Vector b){return Vector(x-b.x,y-b.y);}
	inline Vector operator * (double k){return Vector(x*k,y*k);}
	inline Vector operator / (double k){return Vector(x/k,y/k);}
	inline double operator * (Vector b){return x*b.x+y*b.y;} inline double operator ~ (){return x*x+y*y;}
	inline Vector Norm(){return Vector(y,-x);} inline Vector Unit(){return (*this)/sqrt(~(*this));} inline Vector e(){return x<0 ? Vector(-x,-y) : (*this);}
	inline bool operator == (Vector b){return fabs(x-b.x)+fabs(y-b.y) <= 1e-7;}
};	typedef Vector Point; Point p[MAXN+5], sum, line, res[MAXN+5]; int n, m, ans; bool book[MAXN+5]; double o[MAXN+5], c;
inline bool operator < (Vector a, Vector b){return fabs(a.x-b.x)<=1e-7 ? a.y<b.y : a.x<b.x;}
int main()
{
	n = read(); for(rint i = 1; i <= n; p[i].x = read(), p[i].y = read(), sum = sum+p[i], i++); sum.x /= n, sum.y /= n;
	for(rint i = 1, j; i <= n; i++)
		if(!book[i])
			for(j = 1; j <= n; j++)
				if(!book[j])
					if(p[i]+p[j] == sum+sum)
						book[i] = book[j] = true;
	m = n, n = 0; for(rint i = 1; i <= m; !book[i] ? p[++n] = p[i],0 : 0, i++); if(!n){puts("-1"); return 0;}
	for(rint i = 1, j; i <= n; i++)
	{
		for(line = ((p[i]+p[1])/2-sum).Norm(), j = 1; j <= n; o[j] = line*p[j], j++); sort(o+1,o+n+1);
		for(c = line*sum, j = 1; j <= (n>>1) && fabs(o[j]+o[n-j+1]-c-c) <= 1e-7; j++); j > (n>>1) ?res[++ans] = line.Unit().e(),0 : 0;
	}	sort(res+1,res+ans+1); m = ans; for(rint i = 2; i <= m; ans -= res[i]==res[i-1], i++); printf("%d\n",ans); return 0;
}

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <string>
#include <stack>
#include <set>
#include <cassert>
#include <ctime>
#include <unordered_set>
#include <complex>
#include <queue>

#define vd vector<double>
#define pb push_back
#define all(v) v.begin(), v.end()
#define x first
#define y second
#define mp make_pair
#define forn(i, l) for (int i = 0; i < l; i++)

using namespace std;
typedef pair<int, int> pi;
typedef long double ld;
typedef pair<ld, ld> pd;
typedef long long li;
const int N = 2e3 + 10;
const ld eps = 0.04, eps2 = 0.0001;
const int INF = (int)1e9 + 2;
const long long LINF = 1e16;
const double PI = acos(-1.0);

int n;
pi mas[N];
pd temp[N];
char used[N];
ld cx, cy;
long long Cx, Cy;

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

int main() {
#ifdef _DEBUG
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	scanf("%d", &n);
	forn(i, n) {
		scanf("%d%d", &mas[i].x, &mas[i].y);
		cx += mas[i].x;
		Cx += mas[i].x;
		cy += mas[i].y;
		Cy += mas[i].y;
	}
	cx /= n;
	cy /= n;
	int r = n;
	forn(i, n) {
		if (used[i]) {
			continue;
		}
		if ((n * 1LL * mas[i].x - Cx) == 0 && (n * 1LL * mas[i].y - Cy) == 0) {
			used[i] = 1;
			mas[i].x = mas[i].y = INF;
			r--;
			continue;
		}
		forn(j, i) {
			if (Cx * 2 - n * 1LL * (mas[i].x + mas[j].x) == 0 && Cy * 2 - n * 1LL * (mas[i].y + mas[j].y) == 0) {
				used[i] = used[j] = 1;
				mas[i].x = mas[i].y = INF;
				mas[j].x = mas[j].y = INF;
				r -= 2;
				break;
			}
		}
	}
	sort(mas, mas + n);
	if (r < 1) {
		printf("-1");
		return 0;
	}
	vector<pair<li, li> > ans;
	int sz = 0;
	forn(i, r) {
		ld x2 = (mas[0].x + mas[i].x) * 0.5;
		ld y2 = (mas[0].y + mas[i].y) * 0.5;
		ld a = cx - x2, b = cy - y2;
		ld c = a * x2 + b * y2;
		ld l = (b * b + a * a);
		forn(j, r) {
			ld del = (c - a * mas[j].x - b * mas[j].y) / l;
			temp[j].x = mas[j].x + del * a, temp[j].y = mas[j].y + del * b;
		}
		x2 = (temp[0].x + temp[i].x);
		y2 = (temp[0].y + temp[i].y);
		sort(temp, temp + r);
		//forn(j, r) {
		//	cout << '(' << temp[j].x << ',' << temp[j].y << ')' << endl;
		//}
		ld er = 0;
		forn(j, r) {
			//if (abs(2 * x2 - temp[j].x - temp[r - 1 - j].x) >= eps || abs(2 * y2 - temp[j].y - temp[r - 1 - j].y) >= eps) {
			//	ok = 0;
			//	break;
			//}
			ld t = x2 - temp[j].x - temp[r - 1 - j].x;
			er = max(er, abs(t));
			t = y2 - temp[j].y - temp[r - 1 - j].y;
			er = max(er, abs(t));
		}
			//cout << er << "______________--" << '(' <<x2 << ',' << y2 << ')'<< endl;
		if (er <= eps * n) {
			li A = 2 * Cx - n * 1LL * (mas[0].x + mas[i].x);
			li B = 2 * Cy - n * 1LL * (mas[0].y + mas[i].y);
			if (A < 0) {
				A /= -1;
				B /= -1;
			}
			long long d = gcd(A, B);
			ans.pb(mp(A / d, B / d));
		}
	}
	if (ans.empty()) {
		printf("0");
		return 0;
	}
	sort(all(ans));
	forn(i, ((int)ans.size()) - 1) {
		if ((ans[i].x == ans[i + 1].x) && (ans[i].y == ans[i + 1].y)) {
			sz++;
		}
	}
	printf("%d", ans.size() - sz);
	return 0;
}

#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <cstdio>
#include <cstring>
#include <string>
#include <string.h>
#include <cmath>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <set>
#include <vector>
#include <map>
#include <iomanip>
#include <stdlib.h>
#include <queue>
#include <list>
#include <stack>
#include <bitset>
#include <fstream>
#include <sstream>
#include <random>
#include <assert.h>
#include <unordered_map>
#define eps 1e-7
#define SIZE 2010
#define rep(i, a, b) for (long long i = a; i <= b; ++i)
#define pi acos(-1.0)
#define mp make_pair
#define ll long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
vector<ll> vec;
int num[26];
ll n, cnt, m;
bool vis[SIZE], vs[SIZE];
ll __gcd(ll a, ll b) {
	return b == 0 ? a : __gcd(b, a % b);
}
struct Point {
	ll x, y;
	Point() {}
	Point(ll xx, ll yy) :x(xx), y(yy) {}
	void input() { scanf("%lld %lld", &x, &y); }
}p[SIZE], G, tp[SIZE];
ll cross(Point a, Point b) { return a.x * b.y - a.y * b.x; }	//叉积
ll dot(Point a, Point b) { return a.x * b.x + a.y * b.y; }	//点积
Point operator +(Point a, Point b) { return Point(a.x + b.x, a.y + b.y); }	//向量加法
Point operator -(Point a, Point b) { return Point(a.x - b.x, a.y - b.y); }	//向量减法
Point operator *(Point a, ll t) { return Point(a.x * t, a.y * t); }	//向量数乘
Point operator / (Point a, ll p) { return Point(a.x / p, a.y / p); }	//向量数乘的除法形式
bool operator ==(Point a, Point b) { return (a.x == b.x && a.y == b.y); }
bool operator <(Point a, Point b) { return (a.x < b.x) || (a.x == b.x && a.y < b.y); }

int main() {
	G.x = 0, G.y = 0;
	scanf("%lld", &n);
	rep(i, 1, n) p[i].input();
	rep(i, 1, n) p[i] = p[i] * (2ll * n);
	rep(i, 1, n) G = G + p[i];
	G = G / n;
	rep(i, 1, n) if (G == p[i]) vis[i] = true;
	rep(i, 1, n) {
		if (vis[i]) continue;
		rep(j, (i + 1), n) {
			if (vis[j]) continue;
			if (G == (p[i] + p[j]) / 2) vis[i] = vis[j] = true;
		}
	}
	rep(i, 1, n) {
		if (vis[i]) continue;
		tp[++m] = p[i];
	}
	map<Point, set<int> > MP;
	if (!m) { cout << "-1"; return 0; }
	if (m & 1) {
		rep(i, 1, m) {
			Point tmp = p[i] - G;
			if (tmp.x < 0 || (!tmp.x && tmp.y < 0)) tmp.x = -tmp.x, tmp.y = -tmp.y;
			ll g = __gcd((ll)abs(tmp.x), (ll)abs(tmp.y));
			tmp = tmp / g;
			MP[Point(-tmp.y, tmp.x)].insert(i);
		}
	}
	rep(i, 1, m) {
		rep(j, (i + 1), m) {
			Point tmp = (p[i] + p[j]) / 2 - G;
			if (tmp.x < 0 || (!tmp.x && tmp.y < 0)) tmp.x = -tmp.x, tmp.y = -tmp.y;
			ll g = __gcd((ll)abs(tmp.x), (ll)abs(tmp.y));
			tmp = tmp / g;
			MP[Point(-tmp.y, tmp.x)].insert(i);
			MP[Point(-tmp.y, tmp.x)].insert(j);
		}
	}
	for (auto it : MP) {
		if (it.second.size() < m) continue;
		++cnt;
	}
	cout << cnt;
}

#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef vector<int> vi;
typedef long double ld;
typedef pair<ll,ll> pll;
template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;

#define FOR(i, a, b) for (int i=a; i<(b); i++)
#define F0R(i, a) for (int i=0; i<(a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)

#define sz(x) (int)(x).size()
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound

const int MOD = 1000000007;

int n;
vector<pll> p, P, totest;
set<pll> z;
ll ans = 0;
pll sum;

pll operator+ (const pll& l, const pll& r) {
    return {l.f+r.f,l.s+r.s};
}

pll operator- (const pll& l, const pll& r) {
    return {l.f-r.f,l.s-r.s};
}

void process(pll x) {
    if (x.f == 0 && x.s == 0) return;
    ll g = __gcd(x.f,x.s);
    x.f /= g, x.s /= g;
    if (x.f < 0 || (x.f == 0 && x.s < 0)) x.f *= -1, x.s *= -1;
    totest.pb(x);
}

void test(pll t) {
    vector<ld> cur;
    for (auto a: P) {
        cur.pb((ld)a.f*t.s-(ld)a.s*t.f);
    }
    sort(cur.begin(),cur.end());
    F0R(i,cur.size()) if (cur[i] != -cur[cur.size()-1-i]) return;
    ans++;
}

int main() {
	ios_base::sync_with_stdio(0);cin.tie(0);
	cin >> n; p.resize(n);
	F0R(i,n) {
	    cin >> p[i].f >> p[i].s;
	    sum = sum+p[i];
	    p[i].f *= n, p[i].s *= n;
	}
	F0R(i,n) {
	    p[i] = p[i]-sum;
	    if (z.count(mp(-p[i].f,-p[i].s))) z.erase(mp(-p[i].f,-p[i].s));
	    else z.insert(p[i]);
	}
	for (auto a: z) P.pb(a);
	if (P.size() <= 1) {
	    cout << -1;
	    return 0;
	}
    F0R(i,P.size()) FOR(j,i,P.size()) process(p[i]+p[j]);
    sort(totest.begin(),totest.end());
    F0R(i,totest.size()) {
        int i1 = i;
        while (i < totest.size() && totest[i] == totest[i1]) i++;
        if (2*(i-i1+1) >= P.size()) test(totest[i1]);
    }
    cout << ans;
}

// read!
// ll vs. int!

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define ft first
#define sd second
#define pb(a) push_back(a)
#define mp(a,b) std::make_pair(a,b)
#define ITR(a,b) for(auto a:b)
#define REP(a,b,c) for(register int a=(b),a##end=(c);a<=a##end;++a)
#define DEP(a,b,c) for(register int a=(b),a##end=(c);a>=a##end;--a)
const int MAXN=2000+10;
const ld eps=1e-8;
int T,n,rcnt,lcnt,match[MAXN],ans;
struct node{
	ld x,y;
	inline node operator + (const node &A) const {
		return (node){x+A.x,y+A.y};
	};
	inline node operator - (const node &A) const {
		return (node){x-A.x,y-A.y};
	};
	inline node operator / (const ld &A) const {
		return (node){x/A,y/A};
	};
	inline bool operator < (const node &A) const {
		return fabs(x-A.x)>eps?x<A.x:y<A.y;
	};
	inline bool operator == (const node &A) const {
		return fabs(x-A.x)+fabs(y-A.y)<eps;
	};
	inline bool operator != (const node &A) const {
		return fabs(x-A.x)+fabs(y-A.y)>eps;
	};
};
node pt[MAXN],rest[MAXN],hp,sdw[MAXN],ln[MAXN*MAXN];
template<typename T> inline void read(T &x)
{
	T data=0,w=1;
	char ch=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
	x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
	if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline ld cross(node A,node B)
{
	return (ld)A.x*B.y-(ld)A.y*B.x;
}
int main()
{
	read(n);
	REP(i,1,n)scanf("%Lf%Lf",&pt[i].x,&pt[i].y),hp=hp+pt[i];
	hp=hp/(ld)n;
	std::sort(pt+1,pt+n+1);
	REP(i,1,n)REP(j,i+1,n)if(!match[i]&&!match[j])
		if((pt[i]+pt[j])/2==hp)match[i]=match[j]=1;
	REP(i,1,n)if(!match[i])rest[++rcnt]=pt[i];
	if(rcnt<=2)
	{
		puts("-1");
		return 0;
	}
	REP(i,1,rcnt)REP(j,i+1,rcnt)
	{
		node p=(rest[i]+rest[j])/2-hp;
		if(fabs(p.y)<eps)ln[++lcnt]=(node){1,0};
		else if(fabs(p.x)>0)ln[++lcnt]=(node){1,p.y/p.x};
		else ln[++lcnt]=(node){0,1};
	}
	std::sort(ln+1,ln+lcnt+1);
	REP(i,1,lcnt)
	{
		int j=i;
		while(j<lcnt&&ln[j+1]==ln[i])++j;
		if(j-i+1>=rcnt/2)
		{
			ld nk=-1/ln[i].y;
			REP(k,1,rcnt)
				if(ln[i].x==0)sdw[k].x=rest[k].x,sdw[k].y=0;
				else sdw[k].x=(nk*rest[k].y+rest[k].x)/(nk*nk+1),sdw[k].y=sdw[k].x*nk;
			std::sort(sdw+1,sdw+rcnt+1);
			node np;
			if(ln[i].x==0)np.x=hp.x,np.y=0;
			else np.x=(nk*hp.y+hp.x)/(nk*nk+1),np.y=np.x*nk;
			int mk=1;
			REP(k,1,rcnt>>1)if((sdw[k]+sdw[rcnt-k+1])/2!=np)
			{
				mk=0;
				break;
			}
			if((rcnt&1)&&sdw[(rcnt>>1)+1]!=np)mk=0;
			if(mk)ans++;
		}
		i=j;
	}
	write(ans,'\n');
	return 0;
}

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

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

const int MN = 2010;

ll cross(pii a, pii b) {
    return 1LL * a.first * b.second - 1LL * a.second * b.first;
}

int N;
pii P[MN];
vector<pair<pii, pii> > slope;
int ord[MN], invo[MN];

bool cmp1(pii a, pii b) {
    return a.second < b.second || (a.second == b.second && a.first < b.first);
}
bool cmp2(pair<pii, pii> a, pair<pii, pii> b) {
    if(cross(a.first, b.first) != 0) return cross(a.first, b.first) > 0;
    else return a.second < b.second;
}

struct Line {
    ll a, b, c;
    bool lie(pii p) {
        return a * p.first + b * p.second + c == 0;
    }
} line;
int cnt, ans;

Line getLine(pii p, pii q) {
    return { q.second - p.second, p.first - q.first, 1LL * (q.first - p.first) * p.second - 1LL * (q.second - p.second) * p.first };
}
pii middle(pii a, pii b) {
    return pii((a.first + b.first) / 2, (a.second + b.second) / 2);
}

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

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

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

    sort(P, P + N, cmp1);

    for(int i = 0; i < N; i++) {
        for(int j = i + 1; j < N; j++) {
            int dx = P[j].first - P[i].first;
            int dy = P[j].second - P[i].second;
            slope.push_back({ {dx, dy}, {i, j} });
        }
    }

    sort(slope.begin(), slope.end());

    for(int i = 0; i < N; i++) ord[i] = i, invo[ ord[i] ] = i;
    line = getLine(middle(P[ ord[0] ], P[ ord[N - 1] ]), middle(P[ ord[1] ], P[ ord[N - 2] ]));
    for(int i = 0; i < N; i++) if(line.lie(middle(P[ ord[i] ], P[ ord[N - 1 - i] ]))) cnt++;

    for(int q = 0; q < slope.size(); q++) {
        int a = slope[q].second.first;
        int b = slope[q].second.second;

        if(a <= 1 || b <= 1) {
            swap(ord[ invo[a] ], ord[ invo[b] ]);
            swap(invo[a], invo[b]);

            cnt = 0;
            line = getLine(middle(P[ ord[0] ], P[ ord[N - 1] ]), middle(P[ ord[1] ], P[ ord[N - 2] ]));
            for(int i = 0; i < N; i++) if(line.lie(middle(P[ ord[i] ], P[ ord[N - 1 - i] ]))) cnt++;
            if(cnt == N) ans++;

            continue;
        }

        if(N - 1 - invo[a] == invo[b]) {
            swap(ord[ invo[a] ], ord[ invo[b] ]);
            swap(invo[a], invo[b]);
            if(cnt == N) ans++;
            continue;
        }

        if(line.lie(middle(P[a], P[ ord[ N - 1 - invo[a] ] ]))) cnt -= (invo[a] == N - 1 - invo[a]? 1 : 2);
        if(line.lie(middle(P[b], P[ ord[ N - 1 - invo[b] ] ]))) cnt -= (invo[b] == N - 1 - invo[b]? 1 : 2);
        swap(ord[ invo[a] ], ord[ invo[b] ]);
        swap(invo[a], invo[b]);
        if(line.lie(middle(P[a], P[ ord[ N - 1 - invo[a] ] ]))) cnt += (invo[a] == N - 1 - invo[a]? 1 : 2);
        if(line.lie(middle(P[b], P[ ord[ N - 1 - invo[b] ] ]))) cnt += (invo[b] == N - 1 - invo[b]? 1 : 2);
        if(cnt == N) ans++;
    }

    printf("%d", ans);
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <fstream>
using namespace std;

typedef long double ld;
const ld EPS = 1e-9;

struct pt
{
    ld x, y;
    bool used;
    pt(ld x = 0., ld y = 0.): x(x), y(y) {};
    friend istream& operator>>(istream& is, pt& _pt)
    {
        is >> _pt.x >> _pt.y;
        return is;
    }
    friend ostream& operator<<(ostream& os, pt _pt)
    {
        os << _pt.x << ' ' << _pt.y << ' ';
        return os;
    }
    bool operator==(pt _pt)
    {
        return (abs(_pt.x - this->x) <= EPS && abs(_pt.y - this->y) <= EPS);
    }
    bool operator!=(pt _pt)
    {
        return !(*this == _pt);
    }
    bool operator<(pt _pt)
    {
        return (this->x < _pt.x || (this->x == _pt.x && this->y < _pt.y));
    }
    pt operator+(pt _pt)
    {
        return pt(_pt.x + this->x, _pt.y + this->y);
    }
    pt operator+=(pt _pt)
    {
        return pt(this->x += _pt.x, this->y += _pt.y);
    }
    pt operator/(ld k)
    {
        return pt(this->x / k, this->y / k);
    }
    pt operator/=(ld k)
    {
        return pt(this->x /= k, this->y /= k);
    }
    pt operator*(ld k)
    {
        return pt(this->x * k, this->y * k);
    }
};
struct line
{
    ld a, b, c;
    line(ld a = 0, ld b = 0, ld c = 0): a(a), b(b), c(c) {};
    line(pt p1, pt p2)
    {
        a = p1.y - p2.y;
        b = p2.x - p1.x;
        c = p1.x * p2.y - p1.y * p2.x;
    }
    bool operator==(line l)
    {
        return (abs(this->b * l.a - this->a * l.b) <= EPS && abs(this->c * l.a - this->a * l.c) <= EPS);
    }
};

pt get_proj(line l, pt p)
{
    ld c2 = l.b * p.x - l.a * p.y;
    ld znam = l.a * l.a + l.b * l.b;
    ld x = -(l.a * l.c - c2 * l.b) / znam;
    ld y = -(l.a * c2 + l.b * l.c) / znam;
    return pt(x, y);
}

int main()
{
#ifndef ONLINE_JUDGE
    ifstream cin("input.txt");
#endif
    vector<pt> p, proj;
    int n;
    cin >> n;
    pt cm = {0, 0}, p1;
    for (int i = 0; i < n; ++i)
    {
        cin >> p1;
        p.push_back(p1);
        p[i].used = false;
        cm += p[i];
    }
    cm /= n;
    int cnt = 0;
    for (int i = 0; i < n; ++i)
    {
        if (p[i].used)
            continue;
        if (p[i] == cm)
        {
            ++cnt;
            p[i].used = true;
            continue;
        }
        for (int j = i + 1; j < n; ++j)
        {
            if (p[j].used)
                continue;
            //cout << p[i] << p[j] << '\n';
            if ((p[i] + p[j]) / 2 == cm)
            {
                //cout << "cut\n";
                p[i].used = true;
                p[j].used = true;
                cnt += 2;
                break;
            }
        }
    }
    if (cnt == n)
    {
        cout << -1;
        return 0;
    }
    vector<pt> np;
    for (int i = 0; i < n; ++i)
    {
        if (!p[i].used)
            np.push_back(p[i]);
    }
    n = np.size();
    //cout << cm << '\n';
    pt mid, proj_cm, temp;
    line l, midl;
    bool t;
    vector<line> ans;
    for (int i = 1; i < n; ++i)
    {
        t = true;
        mid = (np[0] + np[i]) / 2;
        //cout << mid << '\n';
        midl = line(mid, cm);
        temp = get_proj(midl, np[0]);
        l = line(temp, np[0]);
        //cout << l.a << ' ' << l.b << ' ' << l.c << '\n';
        proj.clear();
        for (int j = 0; j < n; ++j)
        {
            //cout << get_proj(l, np[j]) << '\n';
            proj.push_back(get_proj(l, np[j]));
        }
        proj_cm = get_proj(l, cm);
        sort(proj.begin(), proj.end());
        for (int j = 0; j < (n + 1) / 2; ++j)
        {
            if ((proj[j] + proj[n - j - 1]) / 2 != proj_cm)
            {
                t = false;
                break;
            }
        }
        //cout << '\n';
        if (t)
        {
            //cout << "yes\n";
            ans.push_back(l);
        }
    }
    //0 - 0
    t = true;
    midl = line(np[0], cm);
    //temp = get_proj(midl, p[0]);
    l = line(-midl.b, midl.a, midl.b * np[0].x - midl.a * np[0].y);
    //cout << l.a << ' ' << l.b << ' ' << l.c << '\n';
    proj.clear();
    for (int j = 0; j < n; ++j)
    {
        //cout << get_proj(l, np[j]) << '\n';
        proj.push_back(get_proj(l, np[j]));
    }
    proj_cm = get_proj(l, cm);
    sort(proj.begin(), proj.end());
    for (int j = 0; j < (n + 1) / 2; ++j)
    {
        //cout << proj[j] << proj[n - j - 1] << '\n';
        if ((proj[j] + proj[n - j - 1]) / 2 != proj_cm)
        {
            t = false;
            break;
        }
    }
    //cout << '\n';
    if (t)
    {
        //cout << "yes\n";
        ans.push_back(l);
    }

    //ans
    vector<int> va(ans.size(), 1);
    for (int i = 0; i < ans.size(); ++i)
    {
        for (int j = i + 1; j < ans.size(); ++j)
            if (ans[i] == ans[j])
            {
                va[i] = 0;
                //va[j] = 0;
            }
    }
    int ansc = 0;
    for (int i : va)
        ansc += i;
    cout << ansc;
}

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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <iomanip>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cstdint>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
#define MP make_pair
#define PB push_back
#define inf 1000000007
#define rep(i,n) for(int i = 0; i < (int)(n); ++i)
#define all(x) (x).begin(),(x).end()

template<typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val){
    std::fill( (T*)array, (T*)(array+N), val );
}

template<class T> inline bool chmax(T &a, T b){
    if(a<b){
        a = b;
        return true;
    }
    return false;
}

template<class T> inline bool chmin(T &a, T b){
    if(a>b){
        a = b;
        return true;
    }
    return false;
}
// template<typename T> class Rational {
// private:
//     static Rational make(const T& x, const T& y){
//         Rational m; return m.num = x, m.den = y, m;
//     }
// public:
//     friend ostream& operator<<(ostream& os, const Rational& rn) {
//         return (os << rn.num << " / " << rn.den);
//     }
//     Rational& operator=(T val){ return *this = Rational(val); }
//     bool operator<(const Rational& val) const { return num*val.den < den*val.num; }
//     bool operator<(const T val) const { return *this < Rational(val); }
//     friend bool operator<(const T val1, const Rational& val2){ return Rational(val1) < val2; }
//     bool operator>(const Rational& val) const { return val < *this; }
//     bool operator>(const T val) const { return *this > Rational(val); }
//     friend bool operator>(const T val1, const Rational& val2){ return Rational(val1) > val2; }
//     bool operator<=(const Rational& val) const { return !(*this > val); }
//     bool operator<=(const T val) const { return *this <= Rational(val); }
//     friend bool operator<=(const T val1, const Rational& val2){ return Rational(val1) <= val2; }
//     bool operator>=(const Rational& val) const { return !(*this < val); }
//     bool operator>=(const T val) const { return *this >= Rational(val); }
//     friend bool operator>=(const T val1, const Rational& val2){ return Rational(val1) >= val2; }
//     bool operator==(const Rational& val) const { return num*val.den == den*val.num; }
//     bool operator==(const T val) const { return *this == Rational(val); }
//     friend bool operator==(const T val1, const Rational& val2){ return Rational(val1) == val2; }
//     bool operator!=(const Rational& val) const { return !(*this == val); }
//     bool operator!=(const T val) const { return *this != Rational(val); }
//     friend bool operator!=(const T val1, const Rational& val2){ return Rational(val1) != val2; }
//     explicit operator bool() const noexcept { return num; }
//     bool operator!() const noexcept { return !static_cast<bool>(*this); }
//     Rational operator+() const { return *this; }
//     Rational operator-() const { return make(-num, den); }
//     friend Rational abs(const Rational& val){ return make(abs(val.num), val.den); }
//     Rational operator+(const Rational& val) const { return make(num*val.den+val.num*den, den*val.den); }
//     Rational operator+(T val) const { return *this + Rational(val); }
//     friend Rational operator+(T a, const Rational& b){ return b + a; }
//     Rational& operator+=(const Rational& val){ return *this = *this + val; }
//     Rational& operator+=(const T& val){ return *this = *this + val; }
//     Rational& operator++(){ return *this += 1; }
//     Rational operator++(int){ return make(num + den, den); }
//     Rational operator-(const Rational& val) const { return make(num*val.den-val.num*den, den*val.den); }
//     Rational operator-(T val) const { return *this - Rational(val); }
//     friend Rational operator-(T a, const Rational& b){ return Rational(a) - b; }
//     Rational& operator-=(const Rational& val){ return *this = *this - val; }
//     Rational& operator-=(const T& val){ return *this = *this - val; }
//     Rational& operator--(){ return *this -= 1; }
//     Rational operator--(int){ return make(num - den, den); }
//     Rational operator*(const Rational& val) const { return make(num*val.num, den*val.den); }
//     Rational operator*(T val) const { return *this * Rational(val); }
//     friend Rational operator*(T a, const Rational& b){ return b * a; }
//     Rational& operator*=(const Rational& val){ return *this = *this * val;}
//     Rational& operator*=(const T& val){ return *this = *this * val; }
//     Rational operator/(const Rational& val) const { return make(num*val.den, den*val.num); }
//     Rational operator/(T val) const { return *this / Rational(val); }
//     friend Rational operator/(T a, const Rational& b){ return Rational(a) / b; }
//     Rational& operator/=(const Rational& val){ return *this / val; }
//     Rational& operator/=(const T& val){ return *this = *this / val; }

//     T num, den;

//     Rational(){}
//     Rational(T num_) : num(num_), den(1){}
//     Rational(T num_, T den_) : num(num_), den(den_){ if(den < 0) num = -num, den = -den; }
// };
// using R = Rational<ll>;

struct point{
    long double x;
    long double y;
    point(){};
};

inline bool up (point p) {
  return p.y > 0 or (p.y == 0 and p.x >= 0);
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n;
    cin >> n;
    vector<ll>x(n),y(n);
    // vector<pair<R,R> >p;
    vector<point> v;
    long double sx = 0.0,sy = 0.0;
    rep(i,n){
        cin >> x[i] >> y[i];
        sx += x[i];
        sy += y[i];
    }
    if(n<=2){
        cout << -1 << endl;
        return 0;
    }
    sx /= (long double)n;
    sy /= (long double)n;
    rep(i,n){
        if(abs(sx-x[i])<=0.0000001&&abs(sy-y[i])<=0.00000001){

        }else{
            // p.push_back(MP(R(x[i]),R(y[i])));
            point a;
            a.x = x[i];
            a.y = y[i];
            v.push_back(a);
        }
    }
    n = v.size();
    sort(v.begin(), v.end(), [] (point a, point b) {
        return up(a) == up(b) ? a.x * b.y > a.y * b.x : up(a) < up(b);
    });

    if(n<=2){
        cout << -1 << endl;
        return 0;
    }
    vector<pair<long double,long double> > res;
    if(n%2==0){
        rep(i,n){
            point a = v[i];
            point b = v[(i+1)%n];
            long double mx = (a.x+b.x)/2.0;
            long double my = (a.y+b.y)/2.0;
            long double rx = (mx-sx);
            long double ry = (my-sy);
            swap(rx,ry);
            ry = -ry;
            long double d = sqrt(rx*rx+ry*ry);
            rx /= d;
            ry /= d;
            vector<long double> s;
            rep(j,n){
                double X = v[j].x;
                double Y = v[j].y;
                s.push_back(rx * (sx-X) + ry*(sy-Y));
            }
            sort(s.begin(),s.end());
            bool ng = 0;
            rep(j,n){
                if(abs(s[j]+s[n-1-j])>0.000001){
                    ng = 1;
                }
            }
            if(!ng){
                res.push_back(MP(rx,ry));
            }
        }
    }else{
        rep(i,n){
            point a = v[i];
            long double mx = a.x;
            long double my = a.y;
            long double rx = (mx-sx);
            long double ry = (my-sy);
            swap(rx,ry);
            ry = -ry;
            long double d = sqrt(rx*rx+ry*ry);
            rx /= d;
            ry /= d;
            if(rx<0){
                rx = -rx;
                ry = -ry;
            }
            vector<long double> s;
            rep(j,n){
                double X = v[j].x;
                double Y = v[j].y;
                s.push_back(rx * (sx-X) + ry*(sy-Y));
            }
            sort(s.begin(),s.end());
            bool ng = 0;
            rep(j,n){
                if(abs(s[j]+s[n-1-j])>0.000001){
                    ng = 1;
                }
            }
            if(!ng){
                res.push_back(MP(rx,ry));
            }
        }
    }
    int m = res.size();
    int sm = m;
    rep(i,m-1){
        if(abs(res[i].first-res[i+1].first)<=0.00001&&abs(res[i].second-res[i+1].second)<=0.00001){
            sm--;
        }
    }
    if(sm<=3){
        cout << sm << endl;
    }else{
        cout << -1 << endl;
    }
    return 0;
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
using namespace std;
typedef long long LL;
LL modu=(1LL<<31)-1;
LL modu2=(1LL<<62)-1;
pair<LL,LL> mult(LL a,LL b){
    if(a==0||b==0){
        return make_pair(0,0);
    }
    int sgn=1;
    if(a<0) sgn*=-1,a=-a;
    if(b<0) sgn*=-1,b=-b;
    LL a1=a>>31,a2=a&modu;
    LL b1=b>>31,b2=b&modu;
    LL c2=a2*b2;
    LL c1=a1*b1;
    LL tmp=a1*b2+a2*b1;
    c2+=(tmp&modu)<<31;
    c1+=tmp>>31;
    if(c2&1<<62L) c2^=1<<62L,c1++;
    c1*=sgn;
    c2*=sgn;
    return make_pair(c1,c2);
}
bool cmp(pair<LL,LL> a,pair<LL,LL> b){
    if(a.first==b.first){
        return a.second<b.second;
    }
    return a.first<b.first;
}
LL x[2000],y[2000],_x[2000],_y[2000];
bool exs[2000];
vector<pair<LL,LL>> K;
vector<LL> dst;
int main(){
    int n,i,j;
    scanf("%d",&n);
    LL cx=0,cy=0;
    for(i=0;i<n;i++){
        scanf("%lld%lld",x+i,y+i);
        cx+=x[i],cy+=y[i];
        _x[i]=x[i],_y[i]=y[i];
        x[i]*=n,y[i]*=n;
    }
    for(i=0;i<n;i++){
        x[i]-=cx,y[i]-=cy;
        exs[i]=x[i]||y[i];
    }
    for(i=0;i<n;i++){
        if(!exs[i]) continue;
        for(j=i+1;j<n;j++){
            if(!exs[j]) continue;
            if(x[i]==-x[j]&&y[i]==-y[j]){
                exs[i]=exs[j]=0;
                break;
            }
        }
    }
    for(i=0,j=0;i<n;i++){
        if(exs[i]){
            x[j]=x[i];
            y[j]=y[i];
            j++;
        }
    }
    n=j;
    if(n==0){
        printf("-1\n");
        return 0;
    }
    LL m2x,m2y,ex,ey,dc2;
    pair<LL,LL> dc;
    bool suc;
    K.clear();
    for(i=0;i<n;i++){
        m2x=x[0]+x[i];
        m2y=y[0]+y[i];
        ey=-m2x;
        ex=m2y;
        dst.clear();
        for(j=0;j<n;j++){
            dst.push_back(_x[j]*ex+_y[j]*ey);
        }
        sort(dst.begin(),dst.end());
        suc=true;
        dc2=dst.front()+dst.back();
        for(j=0;j<=n/2;j++){
            if(dst[j]+dst[n-1-j]!=dc2){
                suc=false;
                break;
            }
        }
        if(suc){
            K.push_back(make_pair(ey,ex));
        }
    }
    for(i=0;i<K.size();i++) exs[i]=1;
    for(i=0;i<K.size();i++){
        for(j=i+1;j<K.size();j++){
            if(mult(K[i].first,K[j].second)==mult(K[i].second,K[j].first)){
                exs[j]=0;
            }
        }
    }
    int cnt=0;
    for(i=0;i<K.size();i++){
        cnt+=exs[i];
    }
    printf("%d\n",cnt);
    return 0;
}

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

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

const int MAXN = 2005;

int N;
int x[MAXN], y[MAXN];
map <pii, int> cnt;
vector <pii> a, b;

void load() {
	scanf("%d", &N);
	for (int i = 0; i < N; i++)
		scanf("%d%d", x + i, y + i);
}

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

bool check(int rx, int ry) {
	return get(a, rx, ry) == get(b, rx, ry);
}

int solve() {
	int sx = 0, sy = 0;
	for (int i = 0; i < N; i++) {
		sx += x[i];
		sy += y[i];
		x[i] *= N;
		y[i] *= N;
	}

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

	for (auto it : cnt)
		for (int i = 0; i < abs(it.second); i++)
			if (it.second > 0)
				a.push_back(it.first);
			else
				b.push_back(it.first);

	assert(a.size() == b.size());

	if (a.empty())
		return -1;

	int sol = 0;
	for (auto it : b)
		sol += check(it.second - a[0].second, a[0].first - it.first);

	return sol;
}

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

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <string>
#include <queue>
#include <set>

using namespace std;

#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define pb push_back
#define mp make_pair
#define fs first
#define sc second

typedef long long ll;
typedef long double ld;

ll x[2010], y[2010];
set<pair<ll, ll> > ln;

ll gcd(ll a, ll b) {
    return a ? gcd(b % a, a) : b;
}

int main() {
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    vector<pair<ll, ll> > p;
    forn (i, n) {
        cin >> x[i] >> y[i];
        p.pb(mp(x[i] * n * 2, y[i] * n * 2));
    }
    sort(p.begin(), p.end());
    ll sx = 0;
    ll sy = 0;
    forn (i, n) {
        sx += x[i] * 2;
        sy += y[i] * 2;
    }
    int ind = -1;
    forn (i, n) {
        if (sx * 2 != p[i].fs + p[n - i - 1].fs ||
            sy * 2 != p[i].sc + p[n - i - 1].sc) {
            if (p[i] < mp(sx * 2 - p[n - i - 1].fs, sy * 2 - p[n - i - 1].sc)) {
                ind = i;
            } else {
                ind = n - i - 1;
            }
            break;
        }
    }
    if (ind == -1) {
        cout << -1 << endl;
        return 0;
    }
    forn (i, n) {
        ll mx = (p[ind].fs + p[i].fs) / 2;
        ll my = (p[ind].sc + p[i].sc) / 2;
        mx -= sx;
        my -= sy;
        vector<ll> res(n);
        forn (j, n) {
            res[j] = x[j] * my - y[j] * mx;
        }
        sort(res.begin(), res.end());
        bool good = true;
        ll sum = res[0] + res.back();
        forn (j, n) {
            if (res[j] + res[n - j - 1] != sum) {
                good = false;
            }
        }
        if (!good) {
            continue;
        }
        if (mx < 0 && my < 0) {
            mx = -mx;
            my = -my;
        }
        ll d = gcd(abs(mx), abs(my));
        mx /= d;
        my /= d;
        ln.insert(mp(mx, my));
    }
    cout << ln.size() << endl;
    return 0;
}

#include <bits/stdc++.h>
#define fr(a, b, c) for(int a = b; a < (int) c; ++a)
using namespace std;
typedef pair<int, int> ii;

const long double INF = 1e100;
const long double EPS = 5e-7;
const long double PI = acos(-1.0);

int cmp(long double a, long double b = 0.0) {
  if (fabs(a-b) < EPS) return 0;
  else if (a < b) return -1;
  return 1;
}

struct PT {
  long double x,y;
  PT() {}
  PT(long double x, long double y) : x(x), y(y){}
  PT(const PT &p) : x(p.x), y(p.y){}
  PT operator +(const PT &p)     const { return PT(x+p.x,y+p.y); }
  PT operator -(const PT &p)     const { return PT(x-p.x,y-p.y); }
  PT operator *(long double c)        const { return PT(x*c,y*c);     }
  PT operator /(long double c)        const { return PT(x/c,y/c);     }
  long double operator *(const PT &p) const { return x*p.x+y*p.y;     }
  long double operator %(const PT &p) const { return x*p.y-y*p.x;     }
  long double operator !()            const { return x*x+y*y;   }
  long double operator ^(const PT &p) const { return (atan2(*this%p,*this*p)); }
  bool operator ==(const PT &p)  const { return cmp(x,p.x)==0 && cmp(y,p.y)==0; }
  bool operator <(const PT &p)   const {
    if (cmp(x,p.x)!=0) return cmp(x,p.x)==-1;
    return cmp(y,p.y)==-1;
  }
};

ostream &operator<<(ostream &os, const PT &p) {
  os << "(" << p.x << "," << p.y << ")";
}

// roda o ponto CCW ou CW ao redor da origem
PT rotateCCW90(PT p) { return PT(-p.y,p.x); }
PT rotateCW90(PT p)  { return PT(p.y,-p.x); }
PT rotateCCW(PT p, long double t) {
  return PT(p.x * cos(t) - p.y * sin(t), p.x * sin(t) + p.y * cos(t));
}

// projeta ponto c na linha através de a e b
// assume a != b
PT projPtLine(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  return a + b * (c*b) / (b*b);
}

// projeta ponto c no segmento através de a e b
PT projPtSeg(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  long double r = b * b;
  if (cmp(r) == 0) return a;
  r = c * b / r;
  if (r < 0) return a;
  if (r > 1) return a+b;
  return a + b * r;
}

bool azul[12345];

int main() {
    srand(time(NULL));
    ios::sync_with_stdio(0);
    int n;
    cin >> n;
    vector<PT> pts;
    PT cent(0,0);
    fr(i, 0, n) {
        int a, b;
        cin >> a >> b;
        pts.push_back(PT(a, b));
        cent = cent + PT(a, b);
    }
    cent = cent / n;
    vector<PT> r_pts;
    fr(i, 0, n) {
        if(pts[i] == cent) {
            azul[i] = true;
        }
        fr(j, i + 1, n) {
            if(!azul[i] && !azul[j] && (pts[i] + pts[j]) / 2 == cent) {
                azul[i] = azul[j] = true;
            }
        }
    }
    fr(i, 0, n) {
        if(!azul[i]) {
            r_pts.push_back(pts[i]);
        }
    }
    pts = r_pts;
    n = pts.size();
    if(n == 0) {
        cout << -1 << endl;
        return 0;
    }

    int ans = 1e9;

    fr(kk, 0, min(3, n)) {
        vector<long double> angles;
        int res = 0;
        int bicho = rand() % n;
        PT a = pts[bicho];
        fr(i, 0, n) {
            PT b = pts[i];
            PT media = (a + b) / 2;
            PT vec = (media - cent);
            PT perp = rotateCCW90(vec);

            long double angle = PT(1, 0) ^ perp;
            if(cmp(angle) < 0) angle += PI;
            bool continua = false;
            for(auto a : angles) {
                if(cmp(angle, a) == 0) {
                    continua = true;
                    break;
                }
            }
            angles.push_back(angle);
            if(continua) continue;

            vector<long double> dists;
            fr(i, 0, n) {
                PT proj = projPtLine(cent, cent + perp, pts[i]);

                int sign = proj < cent ? 1 : -1;

                if (cmp(!(proj - cent)) == 0) continue;
                dists.push_back(!(proj - cent) * sign);
            }
            sort(dists.begin(), dists.end());

            bool ok = true;
            fr(i, 0, dists.size()) {
                if(cmp(dists[i] + dists[dists.size() - i - 1]) != 0) {
                    ok = false;
                    break;
                }
            }
            if(ok) ++res;
        }
        ans = min(ans, res);
    }

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

#include<bits/stdc++.h>
using namespace std;
#define REP(i,st,ed) for(register int i=st,i##end=ed;i<=i##end;++i)
#define DREP(i,st,ed) for(register int i=st,i##end=ed;i>=i##end;--i)
typedef long long ll;
template<typename T>inline bool chkmin(T &x,T y){return (y<x)?(x=y,1):0;}
template<typename T>inline bool chkmax(T &x,T y){return (y>x)?(x=y,1):0;}
inline int read(){
	int x;
	char c;
	int f=1;
	while((c=getchar())!='-' && (c>'9' || c<'0'));
	if(c=='-') f=-1,c=getchar();
	x=c^'0';
	while((c=getchar())>='0' && c<='9') x=(x<<1)+(x<<3)+(c^'0');
	return x*f;
}
inline ll readll(){
	ll x;
	char c;
	int f=1;
	while((c=getchar())!='-' && (c>'9' || c<'0'));
	if(c=='-') f=-1,c=getchar();
	x=c^'0';
	while((c=getchar())>='0' && c<='9') x=(x<<1ll)+(x<<3ll)+(c^'0');
	return x*f;
}
const int maxn=2000+10;
const double eps=(1e-6);
struct point{
	double x,y;
	point operator +(const point &rhs) const{
		return (point){x+rhs.x,y+rhs.y};
	}
	point operator -(const point &rhs) const{
		return (point){x-rhs.x,y-rhs.y};
	}
	point operator /(const int &rhs) const{
		return (point){x/rhs,y/rhs};
	}
	bool operator ==(const point &rhs) const{
		return fabs(x-rhs.x)<=eps && fabs(y-rhs.y)<=eps;
	}
	double operator *(const point &rhs) const{
		return x*rhs.x+y*rhs.y;
	}
	void clear(){
		x=y=0;
	}
}a[maxn],rt,ve;
double p[maxn];
int n,ans,st,id[maxn];
bool cmp(const int A,const int B){
	return p[A]<p[B];
}
inline void get_ans(int x){
	ve=(a[x]+a[st])/2;
	ve=rt-ve;
	ve=(point){ve.y,-ve.x};
	REP(i,1,n) id[i]=i,p[i]=ve*a[i];
	sort(id+1,id+n+1,cmp);
	double num=p[id[1]]+p[id[n]];
	REP(i,1,(n+1)>>1) if(fabs(num-p[id[i]]-p[id[n+1-i]])>eps) return;
	++ans;
}
inline void work(){
	ans=0;
	rt.clear();
	n=read();
	REP(i,1,n) a[i].x=read(),a[i].y=read(),rt=rt+a[i];
	rt=rt/n;
	st=0;
	REP(i,1,n){
		bool flag=1;
		REP(j,1,n) if((a[i]+a[j])/2==rt){
			flag=0;
			break;
		}
		if(flag) st=i;
	}
	if(!st){
		printf("-1\n");
		return;
	}
	REP(i,1,n) get_ans(i);
	printf("%d\n",ans);
}
int main(){
	work();
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
int read(){
	int x=0,f=1;
	char ch=getchar();
	while (!isdigit(ch)&&ch!='-')
		ch=getchar();
	if (ch=='-')
		f=0,ch=getchar();
	while (isdigit(ch))
		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?x:-x;
}
#define double long double
const double Eps=1e-5;
int Dcmp(double x){
	if (fabs(x)<Eps)
		return 0;
	return x<0?-1:1;
}
const int N=2005;
int n;
struct Point{
	double x,y;
	Point(){}
	Point(double _x,double _y){x=_x,y=_y;}
	friend Point operator + (Point A,Point B){return Point(A.x+B.x,A.y+B.y);}
	friend Point operator - (Point A,Point B){return Point(A.x-B.x,A.y-B.y);}
	friend Point operator * (Point A,double x){return Point(A.x*x,A.y*x);}
	friend Point operator / (Point A,double x){return Point(A.x/x,A.y/x);}
	friend bool operator == (Point A,Point B){
		return !Dcmp(A.x-B.x)&&!Dcmp(A.y-B.y);
	}
	friend bool operator < (Point A,Point B){
		if (Dcmp(A.x-B.x))
			return A.x<B.x;
		return A.y<B.y;
	}
}p[N],G(0,0);
int vis[N];
void del(){
	int _n=0;
	for (int i=1;i<=n;i++)
		if (!vis[i])
			p[++_n]=p[i];
	n=_n;
}
Point ans[N];
int tot=0;
multiset <double> S;
multiset <double> :: iterator sp;
void solve(Point L){
	L=Point(L.y,-L.x);
	double Sin=L.y/sqrt(L.x*L.x+L.y*L.y);
	double Cos=L.x/sqrt(L.x*L.x+L.y*L.y);
//	cout << L.x << " " << L.y << endl;
//	cout << "Sin = " << Sin << ", Cos = " << Cos << endl;
	if (Sin<0)
		Sin=-Sin,Cos=-Cos;
	S.clear();
	double dG=Cos*G.x+Sin*G.y;
//	cout << "dG = " << dG << endl;
	for (int i=1;i<=n;i++){
		double d=Cos*p[i].x+Sin*p[i].y;
//		cout << "d" << i << " = " << d << endl;
		if (!Dcmp(d-dG))
			continue;
		sp=S.lower_bound(dG*2-d-Eps);
		if (!Dcmp(d+*sp-dG*2))
			S.erase(sp);
		else
			S.insert(d);
	}
	if (S.empty())
		ans[++tot]=Point(Sin,Cos);
//	for (auto d : S)
//		cout << d << " ";
//	cout << "\n------------------------\n";
}
int main(){
	n=read();
	for (int i=1;i<=n;i++){
		p[i].x=read(),p[i].y=read();
		G=G+p[i];
	}
	G=G/n;
	for (int i=1;i<=n;i++){
		if (vis[i])
			continue;
		for (int j=1;j<=n;j++)
			if (G*2-p[i]==p[j]){
				vis[i]=vis[j]=1;
				break;
			}
	}
	del();
	if (!n)
		return puts("-1"),0;
	for (int i=1;i<=n;i++)
		solve((p[1]+p[i])/2-G);
	sort(ans+1,ans+tot+1);
	int res=min(tot,1);
	for (int i=2;i<=tot;i++)
		if (!(ans[i]==ans[i-1]))
			res++;
	cout << res;
	return 0;
}
/*
4
2 4
1 2
0 0
-2 -4
*/

#include <bits/stdc++.h>
#define fr(a, b, c) for(int a = b; a < (int) c; ++a)
using namespace std;
typedef pair<int, int> ii;

const double INF = 1e100;
const double EPS = 1e-8;
const double PI = acos(-1.0);

int cmp(double a, double b = 0.0) {
  if (fabs(a-b) < EPS) return 0;
  else if (a < b) return -1;
  return 1;
}

struct PT {
  double x,y;
  PT() {}
  PT(double x, double y) : x(x), y(y){}
  PT(const PT &p) : x(p.x), y(p.y){}
  PT operator +(const PT &p)     const { return PT(x+p.x,y+p.y); }
  PT operator -(const PT &p)     const { return PT(x-p.x,y-p.y); }
  PT operator *(double c)        const { return PT(x*c,y*c);     }
  PT operator /(double c)        const { return PT(x/c,y/c);     }
  double operator *(const PT &p) const { return x*p.x+y*p.y;     }
  double operator %(const PT &p) const { return x*p.y-y*p.x;     }
  double operator !()            const { return sqrt(x*x+y*y);   }
  double operator ^(const PT &p) const { return fabs(atan2(*this%p,*this*p)); }
  bool operator ==(const PT &p)  const { return cmp(x,p.x)==0 && cmp(y,p.y)==0; }
  bool operator <(const PT &p)   const {
    if (cmp(x,p.x)!=0) return cmp(x,p.x)==-1;
    return cmp(y,p.y)==-1;
  }
};

ostream &operator<<(ostream &os, const PT &p) {
  os << "(" << p.x << "," << p.y << ")";
}

// roda o ponto CCW ou CW ao redor da origem
PT rotateCCW90(PT p) { return PT(-p.y,p.x); }
PT rotateCW90(PT p)  { return PT(p.y,-p.x); }
PT rotateCCW(PT p, double t) {
  return PT(p.x * cos(t) - p.y * sin(t), p.x * sin(t) + p.y * cos(t));
}

// projeta ponto c na linha através de a e b
// assume a != b
PT projPtLine(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  return a + b * (c*b) / (b*b);
}

// projeta ponto c no segmento através de a e b
PT projPtSeg(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  double r = b * b;
  if (cmp(r) == 0) return a;
  r = c * b / r;
  if (r < 0) return a;
  if (r > 1) return a+b;
  return a + b * r;
}

int main() {
    ios::sync_with_stdio(0);
    int n;
    cin >> n;
    vector<PT> pts;
    PT cent(0,0);
    fr(i, 0, n) {
        int a, b;
        cin >> a >> b;
        pts.push_back(PT(a, b));
        cent = cent + PT(a, b);
    }
    cent = cent / n;
    PT a = pts[0];
    bool inf = true;
    int res = 0;
    vector<double> angles;
    fr(i, 0, n) {
        PT b = pts[i];
        PT media = (a + b) / 2;
        PT vec = (media - cent);
        if(vec == PT(0,0)) {
            continue;
        }
        if(i) inf = false;
        PT perp = rotateCCW90(vec);
        PT cent_proj = projPtLine(PT(0, 0), perp, cent);

        double angle = PT(1, 0) ^ cent_proj;
        bool continua = false;
        for(auto a : angles) {
            if(cmp(angle, a) == 0) {
                continua = true;
                break;
            }
        }
        angles.push_back(angle);
        if(continua) continue;

        vector<double> dists;
        fr(i, 0, n) {
            PT proj = projPtLine(PT(0, 0), perp, pts[i]);

            double prod_scalar = (perp - PT(0,0)) * (proj - cent_proj);
            int sign = cmp(prod_scalar, 0);
            if(sign == 0) sign = 1;
            dists.push_back(!(proj - cent_proj) * sign);
        }
        sort(dists.begin(), dists.end());
        bool ok = true;
        fr(i, 0, n) {
            if(cmp(dists[i] + dists[n - i - 1]) != 0) {
                ok = false;
                break;
            }
        }
        if(ok) ++res;
    }
    if(inf)
        cout << -1 << endl;
    else
        cout << res << endl;
    return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#include <cstdio>
#include <stdlib.h>
#include <stack>
#include <numeric>
#include <bitset>
#include <cctype>
#include <list>
#include <assert.h>
#include <random>
#include <unordered_map>
#include <ctime>
typedef  long long ll;
using namespace std;
#define INF 2147483647
#define infL (1LL<<60)
#define inf (1<<30)
#define inf9 (1000000000)
#define MOD 1000000007
#define EPS 1e-9
#define Gr 9.8
#define PI acos(-1)
#define REP(i,n) for(int (i)=0;(i)<(int)(n);(i)++)
#define REQ(i,n) for(int (i)=1;(i)<=(int)(n);(i)++)
#define lch (rt<<1)
#define rch (rt<<1|1)
#define readmp(n) for(int i=0,u,v;i<n;i++) {scanf("%d%d",&u,&v); mp[u].push_back(v); mp[v].push_back(u);}
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef long double ld;
typedef unsigned int uint;
#define MAX 2105
bool debug = 0;
int n,m,k;
int dx[4] = {0,1,0,-1}, dy[4] = {1,0,-1,0};
string direc="RDLU";
ll ln, lk, lm;
void etp(bool f = 0) {
    puts(f ?"YES" : "NO");
    exit(0);
}
void addmod(int &x, int y, int mod = MOD) {
    assert(y>=0);
    x+=y; if (x>=mod) x-=mod;
    assert(x>=0 && x<mod);
}
void et() {
    puts("-1"); exit(0);
}
ll fastPow(ll x, ll y, int mod=MOD) {
    ll ans = 1;
    while(y>0) {
        if(y&1) ans = (x * ans)%mod;
        x = x*x%mod;
        y>>=1;
    }
    return ans;
}
ll gcd1(ll x, ll y) {
    ll z = y;
    while(x%y!=0) {
        z = x%y; x = y; y = z;
    }
    return z;
}

typedef ll ValType;
struct Point {
    ValType x, y;
    Point() { }
    Point(ValType x, ValType y) : x(x), y(y) { }
    ld abs() const { return hypot(x, y); }
    ld arg() const { return atan2(y, x); }
    Point operator*(double o) const { return Point(x * o, y * o); }
    Point operator+(const Point& o) const { return Point(x + o.x, y + o.y); }
    Point operator-(const Point& o) const { return Point(x - o.x, y - o.y); }
    bool operator<(const Point& o) const { return x < o.x - EPS || (x < o.x + EPS && y < o.y - EPS); }
    friend bool operator == (const Point &r1,const Point &r2)
    {return r1.x==r2.x&&r1.y==r2.y;}

    Point scale(double o) const { return *this * (o / abs()); }
    Point rotY() const { return Point(-y, x); }
    Point rotX() const { return Point(y, -x); }
    Point div(ll z) const { return Point(x/z,y/z); }
    ValType cross(Point b) const {return x*b.y- b.x*y;}
    ValType dot(Point b) const {return x*b.x + y*b.y;}
    ld disToSeg(Point &a, Point &b) {
        return fabs(((*this)-a).cross(b-a) / (b-a).abs());
    }
    pair<ll, ll> getVec() {
        if (x==0) return {0, 1};
        if (y==0) return {1, 0};
        ll gg = gcd1(::abs(x),::abs(y));
        ll px=x/gg,py=y/gg;
        if (px<0) {
            px*=-1; py*=-1;
        }
        return {px,py};
    }
    void readin() {
        scanf("%lld%lld", &x, &y);
    }
};

Point p[MAX], C, rp[MAX];
 int cnt;
ll ttPs;
map<pll,int> mp;
bool vis[MAX];
void fmain(int ID) {
    scanf("%d", &n);
    if (n<=2) et();

    C = Point(0, 0);
    REQ(i,n) {
        p[i].readin();
        p[i] = p[i]*2*n;
        C = C+p[i];
    }
    C.x /= n; C.y /=n;
    ttPs = n/2;
    REQ(i,n) if (!vis[i]) for(int j=i+1;j<=n;j++) {
        Point sc = (p[i]+p[j]).div(2);
        if (sc==C) {
            ttPs--;
            vis[i]=1;vis[j]=1; break;
        }

        Point pp = sc-C;
        mp[pp.getVec()]++;
    }
    if (ttPs==0) et();
    REQ(i,n) if (!vis[i]) rp[++cnt]=p[i];

    int ans = 0;
    for(auto &pp : mp) if (pp.second>=ttPs) {
        //k = pp.second / -pp.fisrt
        vector<ll> vp;
        REQ(i,cnt) {
            ll zd = rp[i].x * pp.first.second - rp[i].y * pp.first.first;
            vp.push_back(zd);
        }
        sort(vp.begin(), vp.end());
        bool ok = 1;
        for(int i=1,j=cnt-2;i<=j;i++,j--) {
            if (vp[i]+vp[j]!=vp[0]+vp[n-1]) {
                ok=0; break;
            }
        }
        if (ok) ans++;
    }
    printf("%d\n", ans);
}
int main() {
    int t=1;
//    scanf("%d", &t);
    REQ(i,t) {
        fmain(i);
    }
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
int n,id[2005],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};
	}
	P operator /(double a){
		return (P){x/a,y/a};
	}
	double operator *(P a){
		return x*a.x+y*a.y;
	}
	bool operator ==(P a){
		return fabs(x-a.x)<1e-9&&fabs(y-a.y)<1e-9;
	}
}p[2005],rt,mid,vec;
pair<double,int> a[2005];
bool check(int pos){
	mid=(p[x]+p[pos])/2;
	vec=rt-mid;
	vec=(P){vec.y,-vec.x};
	for (int i=1;i<=n;i++)
		a[i]=make_pair(vec*p[i],i);
	sort(a+1,a+n+1);
	for (int i=1;i<=n;i++)
		id[a[i].second]=i;
	//if (id[x]+id[pos]!=n+1) return 0;
	double flag=a[1].first+a[n].first;
	for (int i=1;i<=n;i++)
		if (abs(a[i].first+a[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);
		rt=rt+p[i];
	}
	rt=rt/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]==rt+rt) is=1;
		if (!is) inf=0,x=i;
	}
	if (inf)
		return puts("-1"),0;
	int ans=0;
	for (int i=1;i<=n;i++)
		if (check(i)) ans++;
	printf("%d",ans);
}

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <iomanip>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cstdint>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
#define MP make_pair
#define PB push_back
#define inf 1000000007
#define rep(i,n) for(int i = 0; i < (int)(n); ++i)
#define all(x) (x).begin(),(x).end()

template<typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val){
    std::fill( (T*)array, (T*)(array+N), val );
}

template<class T> inline bool chmax(T &a, T b){
    if(a<b){
        a = b;
        return true;
    }
    return false;
}

template<class T> inline bool chmin(T &a, T b){
    if(a>b){
        a = b;
        return true;
    }
    return false;
}
// template<typename T> class Rational {
// private:
//     static Rational make(const T& x, const T& y){
//         Rational m; return m.num = x, m.den = y, m;
//     }
// public:
//     friend ostream& operator<<(ostream& os, const Rational& rn) {
//         return (os << rn.num << " / " << rn.den);
//     }
//     Rational& operator=(T val){ return *this = Rational(val); }
//     bool operator<(const Rational& val) const { return num*val.den < den*val.num; }
//     bool operator<(const T val) const { return *this < Rational(val); }
//     friend bool operator<(const T val1, const Rational& val2){ return Rational(val1) < val2; }
//     bool operator>(const Rational& val) const { return val < *this; }
//     bool operator>(const T val) const { return *this > Rational(val); }
//     friend bool operator>(const T val1, const Rational& val2){ return Rational(val1) > val2; }
//     bool operator<=(const Rational& val) const { return !(*this > val); }
//     bool operator<=(const T val) const { return *this <= Rational(val); }
//     friend bool operator<=(const T val1, const Rational& val2){ return Rational(val1) <= val2; }
//     bool operator>=(const Rational& val) const { return !(*this < val); }
//     bool operator>=(const T val) const { return *this >= Rational(val); }
//     friend bool operator>=(const T val1, const Rational& val2){ return Rational(val1) >= val2; }
//     bool operator==(const Rational& val) const { return num*val.den == den*val.num; }
//     bool operator==(const T val) const { return *this == Rational(val); }
//     friend bool operator==(const T val1, const Rational& val2){ return Rational(val1) == val2; }
//     bool operator!=(const Rational& val) const { return !(*this == val); }
//     bool operator!=(const T val) const { return *this != Rational(val); }
//     friend bool operator!=(const T val1, const Rational& val2){ return Rational(val1) != val2; }
//     explicit operator bool() const noexcept { return num; }
//     bool operator!() const noexcept { return !static_cast<bool>(*this); }
//     Rational operator+() const { return *this; }
//     Rational operator-() const { return make(-num, den); }
//     friend Rational abs(const Rational& val){ return make(abs(val.num), val.den); }
//     Rational operator+(const Rational& val) const { return make(num*val.den+val.num*den, den*val.den); }
//     Rational operator+(T val) const { return *this + Rational(val); }
//     friend Rational operator+(T a, const Rational& b){ return b + a; }
//     Rational& operator+=(const Rational& val){ return *this = *this + val; }
//     Rational& operator+=(const T& val){ return *this = *this + val; }
//     Rational& operator++(){ return *this += 1; }
//     Rational operator++(int){ return make(num + den, den); }
//     Rational operator-(const Rational& val) const { return make(num*val.den-val.num*den, den*val.den); }
//     Rational operator-(T val) const { return *this - Rational(val); }
//     friend Rational operator-(T a, const Rational& b){ return Rational(a) - b; }
//     Rational& operator-=(const Rational& val){ return *this = *this - val; }
//     Rational& operator-=(const T& val){ return *this = *this - val; }
//     Rational& operator--(){ return *this -= 1; }
//     Rational operator--(int){ return make(num - den, den); }
//     Rational operator*(const Rational& val) const { return make(num*val.num, den*val.den); }
//     Rational operator*(T val) const { return *this * Rational(val); }
//     friend Rational operator*(T a, const Rational& b){ return b * a; }
//     Rational& operator*=(const Rational& val){ return *this = *this * val;}
//     Rational& operator*=(const T& val){ return *this = *this * val; }
//     Rational operator/(const Rational& val) const { return make(num*val.den, den*val.num); }
//     Rational operator/(T val) const { return *this / Rational(val); }
//     friend Rational operator/(T a, const Rational& b){ return Rational(a) / b; }
//     Rational& operator/=(const Rational& val){ return *this / val; }
//     Rational& operator/=(const T& val){ return *this = *this / val; }

//     T num, den;

//     Rational(){}
//     Rational(T num_) : num(num_), den(1){}
//     Rational(T num_, T den_) : num(num_), den(den_){ if(den < 0) num = -num, den = -den; }
// };
// using R = Rational<ll>;
#define EPS 1e-8
struct point{
    long double x;
    long double y;
    point(){};
};

inline bool up (point p) {
  return p.y > 0 or (p.y == 0 and p.x >= 0);
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n;
    cin >> n;
    vector<ll>x(n),y(n);
    // vector<pair<R,R> >p;
    vector<point> v;
    long double sx = 0.0,sy = 0.0;
    rep(i,n){
        cin >> x[i] >> y[i];
        sx += x[i];
        sy += y[i];
    }
    if(n<=2){
        cout << -1 << endl;
        return 0;
    }
    sx /= (long double)n;
    sy /= (long double)n;
    rep(i,n){
        if(abs(sx-x[i])<=EPS&&abs(sy-y[i])<=EPS){

        }else{
            // p.push_back(MP(R(x[i]),R(y[i])));
            point a;
            a.x = x[i];
            a.y = y[i];
            v.push_back(a);
        }
    }
    n = v.size();
    sort(v.begin(), v.end(), [] (point a, point b) {
        return up(a) == up(b) ? a.x * b.y > a.y * b.x : up(a) < up(b);
    });

    if(n<=2){
        cout << -1 << endl;
        return 0;
    }
    vector<pair<long double,long double> > res;
    if(n%2==0){
        rep(i,n){
            point a = v[i];
            point b = v[(i+1)%n];
            long double mx = (a.x+b.x)/2.0;
            long double my = (a.y+b.y)/2.0;
            long double rx = (mx-sx);
            long double ry = (my-sy);
            swap(rx,ry);
            ry = -ry;
            long double d = sqrt(rx*rx+ry*ry);

            rx /= d;
            ry /= d;
            if(rx<0){
                rx = -rx;
                ry = -ry;
            }
            vector<long double> s;
            rep(j,n){
                double X = v[j].x;
                double Y = v[j].y;
                s.push_back(rx * (sx-X) + ry*(sy-Y));
            }
            sort(s.begin(),s.end());
            bool ng = 0;
            rep(j,n){
                if(abs(s[j]+s[n-1-j])>EPS){
                    ng = 1;
                }
            }
            if(!ng){
                res.push_back(MP(rx,ry));
            }
        }
    }else{
        rep(i,n){
            point a = v[i];
            long double mx = a.x;
            long double my = a.y;
            long double rx = (mx-sx);
            long double ry = (my-sy);
            swap(rx,ry);
            ry = -ry;
            long double d = sqrt(rx*rx+ry*ry);
            rx /= d;
            ry /= d;
            if(rx<0){
                rx = -rx;
                ry = -ry;
            }
            vector<long double> s;
            rep(j,n){
                double X = v[j].x;
                double Y = v[j].y;
                s.push_back(rx * (sx-X) + ry*(sy-Y));
            }
            sort(s.begin(),s.end());
            bool ng = 0;
            rep(j,n){
                if(abs(s[j]+s[n-1-j])>EPS){
                    ng = 1;
                }
            }
            if(!ng){
                res.push_back(MP(rx,ry));
            }
        }
    }
    sort(res.begin(),res.end());
    int m = res.size();
    int sm = m;
    rep(i,m-1){
        if(abs(res[i].first-res[i+1].first)<=EPS&&abs(res[i].second-res[i+1].second)<=EPS){
            sm--;
        }
    }
    if(sm<=3){
        cout << sm << endl;
    }else{
        cout << -1 << endl;
    }
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define REP(i,st,ed) for(register int i=st,i##end=ed;i<=i##end;++i)
#define DREP(i,st,ed) for(register int i=st,i##end=ed;i>=i##end;--i)
typedef long long ll;
template<typename T>inline bool chkmin(T &x,T y){return (y<x)?(x=y,1):0;}
template<typename T>inline bool chkmax(T &x,T y){return (y>x)?(x=y,1):0;}
inline int read(){
	int x;
	char c;
	int f=1;
	while((c=getchar())!='-' && (c>'9' || c<'0'));
	if(c=='-') f=-1,c=getchar();
	x=c^'0';
	while((c=getchar())>='0' && c<='9') x=(x<<1)+(x<<3)+(c^'0');
	return x*f;
}
inline ll readll(){
	ll x;
	char c;
	int f=1;
	while((c=getchar())!='-' && (c>'9' || c<'0'));
	if(c=='-') f=-1,c=getchar();
	x=c^'0';
	while((c=getchar())>='0' && c<='9') x=(x<<1ll)+(x<<3ll)+(c^'0');
	return x*f;
}
const int maxn=2000+10,inf=0x3f3f3f3f;
const long double eps=(1e-9);
struct point{
	long double x,y;
	point operator +(const point &rhs) const{
		return (point){x+rhs.x,y+rhs.y};
	}
	point operator -(const point &rhs) const{
		return (point){x-rhs.x,y-rhs.y};
	}
	point operator /(const int &rhs) const{
		return (point){x/rhs,y/rhs};
	}
	bool operator ==(const point &rhs) const{
		return fabs(x-rhs.x)<=eps && fabs(y-rhs.y)<=eps;
	}
	long double operator *(const point &rhs) const{
		return x*rhs.x+y*rhs.y;
	}
	void clear(){
		x=y=0;
	}
}a[maxn],rt,ve;
long double p[maxn];
int n,ans,st,id[maxn];
bool cmp(const int A,const int B){
	return p[A]<p[B] || (p[A]==p[B] && A<B);
}
inline void get_ans(int x){
	ve=(a[x]+a[st])/2;
	ve=rt-ve;
	ve=(point){ve.y,-ve.x};
	REP(i,1,n) id[i]=i,p[i]=ve*a[i];
	sort(id+1,id+n+1,cmp);
	long double num=p[id[1]]+p[id[n]];
	REP(i,1,n/2+1) if(fabs(num-p[id[i]]-p[id[n+1-i]])>eps) return;
	int l1=inf,r1=0,l2=inf,r2=0;
	REP(i,1,n){
		if(p[id[i]]==p[x]) chkmin(l1,i),chkmax(r1,i);
		if(p[id[i]]==p[st]) chkmin(l2,i),chkmax(r2,i);
	}
	if(n+1<l1+l2 || n+1>r1+r2) return;
	if(x==st && (n+1)%2==1) return;
	++ans;
}
inline void work(){
	ans=0;
	rt.clear();
	n=read();
	REP(i,1,n) a[i].x=read(),a[i].y=read(),rt=rt+a[i];
	rt=rt/n;
	st=0;
	REP(i,1,n){
		bool flag=1;
		REP(j,1,n) if((a[i]+a[j])/2==rt){
			flag=0;
			break;
		}
		if(flag) st=i;
	}
	if(!st){
		printf("-1\n");
		return;
	}
	REP(i,1,n) get_ans(i);
	printf("%d\n",ans);
}
int main(){
	work();
	return 0;
}

//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;}
int n;
pair<int,int> 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];
	bool ok=0;
	for(int i=1;i<=n;i++)
	{
		if(b[i]+b[n-i+1]!=M2)return false;
	}
	return true;
}
bool 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;
//		cerr<<i<<","<<j<<" "<<p<<","<<q<<endl;
		if(q==0&&p!=0)continue;
		if(q==0&&p==0)return false;
		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));
		}
	}
	return true;
}
int main()
{
	geti(n);
	if(n<=2)
	{
		puts("-1");
		return 0;
	}
	for(int i=1;i<=n;i++)
	{
		getii(a[i].FF,a[i].SS);
		sumx+=a[i].FF;
		sumy+=a[i].SS;
	}
	if(check(0,1,1))st.insert(MP(1,0));
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		cnt+=go(i);
		if(cnt>=2)break;
	}
	if(cnt==0)
	{
		puts("-1");
		return 0;
	}
//	foreach(it,st)cerr<<it->FF<<","<<it->SS<<endl;
	cout<<st.size()<<endl;
	return 0;
}

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <utility>
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define per(i,r,l) for(int i=(r);i>=(l);--i)
using namespace std;
typedef long double Ld;
const Ld eps=1e-9;
const int maxn=2010;
int n,cnt,f[maxn],ans;
Ld x[maxn],y[maxn],px,py,vx,vy;
bool b[maxn];
pair<Ld,int> p[maxn];
int cmp(Ld x){
	if(x>eps) return 1;
	if(x<-eps) return -1;
	return 0;
}
int main(){
	scanf("%d",&n);
	rep(i,1,n) scanf("%Lf%Lf",&x[i],&y[i]),px+=x[i],py+=y[i];
	px/=n;py/=n;
	memset(b,true,sizeof(b));
	rep(i,1,n) if(!cmp(x[i]-px)&&!cmp(y[i]-py)) b[i]=false;
	rep(i,1,n) rep(j,i+1,n)
		if(!cmp(x[i]+x[j]-2*px)&&!cmp(y[i]+y[j]-2*py)) b[i]=b[j]=false;
	int cnt=0;
	rep(i,1,n) if(b[i]) x[++cnt]=x[i],y[cnt]=y[i];
	if(cnt<=2) return puts("-1"),0;
	rep(i,1,cnt){
		vx=2*py-y[1]-y[i],vy=x[1]+x[i]-2*px;
		rep(j,1,n) p[j]=make_pair(vx*(px-x[j])+vy*(py-y[j]),j);
		sort(p+1,p+n+1);
		rep(j,1,n) f[p[j].second]=j;
		if(f[1]+f[i]!=n+1) continue;
		Ld t=p[1].first+p[n].first;bool flag=true;
		rep(j,1,n) if(cmp(p[j].first+p[n+1-j].first-t)){
			flag=false;break;
		}
		if(flag) ++ans;
	}
	printf("%d\n",ans);
	return 0;
}

#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;
}

#define double long double

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;
	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;
	sum.x /= n, sum.y /= n;
	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 i = 0; i < a.size() && flg; i ++)
			if (fabs(a[i] - b[i]) > 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 <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <iomanip>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cstdint>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
#define MP make_pair
#define PB push_back
#define inf 1000000007
#define rep(i,n) for(int i = 0; i < (int)(n); ++i)
#define all(x) (x).begin(),(x).end()

template<typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val){
    std::fill( (T*)array, (T*)(array+N), val );
}

template<class T> inline bool chmax(T &a, T b){
    if(a<b){
        a = b;
        return true;
    }
    return false;
}

template<class T> inline bool chmin(T &a, T b){
    if(a>b){
        a = b;
        return true;
    }
    return false;
}
// template<typename T> class Rational {
// private:
//     static Rational make(const T& x, const T& y){
//         Rational m; return m.num = x, m.den = y, m;
//     }
// public:
//     friend ostream& operator<<(ostream& os, const Rational& rn) {
//         return (os << rn.num << " / " << rn.den);
//     }
//     Rational& operator=(T val){ return *this = Rational(val); }
//     bool operator<(const Rational& val) const { return num*val.den < den*val.num; }
//     bool operator<(const T val) const { return *this < Rational(val); }
//     friend bool operator<(const T val1, const Rational& val2){ return Rational(val1) < val2; }
//     bool operator>(const Rational& val) const { return val < *this; }
//     bool operator>(const T val) const { return *this > Rational(val); }
//     friend bool operator>(const T val1, const Rational& val2){ return Rational(val1) > val2; }
//     bool operator<=(const Rational& val) const { return !(*this > val); }
//     bool operator<=(const T val) const { return *this <= Rational(val); }
//     friend bool operator<=(const T val1, const Rational& val2){ return Rational(val1) <= val2; }
//     bool operator>=(const Rational& val) const { return !(*this < val); }
//     bool operator>=(const T val) const { return *this >= Rational(val); }
//     friend bool operator>=(const T val1, const Rational& val2){ return Rational(val1) >= val2; }
//     bool operator==(const Rational& val) const { return num*val.den == den*val.num; }
//     bool operator==(const T val) const { return *this == Rational(val); }
//     friend bool operator==(const T val1, const Rational& val2){ return Rational(val1) == val2; }
//     bool operator!=(const Rational& val) const { return !(*this == val); }
//     bool operator!=(const T val) const { return *this != Rational(val); }
//     friend bool operator!=(const T val1, const Rational& val2){ return Rational(val1) != val2; }
//     explicit operator bool() const noexcept { return num; }
//     bool operator!() const noexcept { return !static_cast<bool>(*this); }
//     Rational operator+() const { return *this; }
//     Rational operator-() const { return make(-num, den); }
//     friend Rational abs(const Rational& val){ return make(abs(val.num), val.den); }
//     Rational operator+(const Rational& val) const { return make(num*val.den+val.num*den, den*val.den); }
//     Rational operator+(T val) const { return *this + Rational(val); }
//     friend Rational operator+(T a, const Rational& b){ return b + a; }
//     Rational& operator+=(const Rational& val){ return *this = *this + val; }
//     Rational& operator+=(const T& val){ return *this = *this + val; }
//     Rational& operator++(){ return *this += 1; }
//     Rational operator++(int){ return make(num + den, den); }
//     Rational operator-(const Rational& val) const { return make(num*val.den-val.num*den, den*val.den); }
//     Rational operator-(T val) const { return *this - Rational(val); }
//     friend Rational operator-(T a, const Rational& b){ return Rational(a) - b; }
//     Rational& operator-=(const Rational& val){ return *this = *this - val; }
//     Rational& operator-=(const T& val){ return *this = *this - val; }
//     Rational& operator--(){ return *this -= 1; }
//     Rational operator--(int){ return make(num - den, den); }
//     Rational operator*(const Rational& val) const { return make(num*val.num, den*val.den); }
//     Rational operator*(T val) const { return *this * Rational(val); }
//     friend Rational operator*(T a, const Rational& b){ return b * a; }
//     Rational& operator*=(const Rational& val){ return *this = *this * val;}
//     Rational& operator*=(const T& val){ return *this = *this * val; }
//     Rational operator/(const Rational& val) const { return make(num*val.den, den*val.num); }
//     Rational operator/(T val) const { return *this / Rational(val); }
//     friend Rational operator/(T a, const Rational& b){ return Rational(a) / b; }
//     Rational& operator/=(const Rational& val){ return *this / val; }
//     Rational& operator/=(const T& val){ return *this = *this / val; }

//     T num, den;

//     Rational(){}
//     Rational(T num_) : num(num_), den(1){}
//     Rational(T num_, T den_) : num(num_), den(den_){ if(den < 0) num = -num, den = -den; }
// };
// using R = Rational<ll>;

struct point{
    long double x;
    long double y;
    point(){};
};

inline bool up (point p) {
  return p.y > 0 or (p.y == 0 and p.x >= 0);
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n;
    cin >> n;
    vector<ll>x(n),y(n);
    // vector<pair<R,R> >p;
    vector<point> v;
    long double sx = 0.0,sy = 0.0;
    rep(i,n){
        cin >> x[i] >> y[i];
        sx += x[i];
        sy += y[i];
    }
    if(n<=2){
        cout << -1 << endl;
        return 0;
    }
    sx /= (long double)n;
    sy /= (long double)n;
    rep(i,n){
        if(abs(sx-x[i])<=0.0000001&&abs(sy-y[i])<=0.00000001){

        }else{
            // p.push_back(MP(R(x[i]),R(y[i])));
            point a;
            a.x = x[i];
            a.y = y[i];
            v.push_back(a);
        }
    }
    n = v.size();
    sort(v.begin(), v.end(), [] (point a, point b) {
        return up(a) == up(b) ? a.x * b.y > a.y * b.x : up(a) < up(b);
    });
    vector<pair<long double,long double> > res;
    if(n%2==0){
        rep(i,n){
            point a = v[i];
            point b = v[(i+1)%n];
            long double mx = (a.x+b.x)/2.0;
            long double my = (a.y+b.y)/2.0;
            long double rx = (mx-sx);
            long double ry = (my-sy);
            swap(rx,ry);
            ry = -ry;
            long double d = sqrt(rx*rx+ry*ry);
            rx /= d;
            ry /= d;
            vector<long double> s;
            rep(j,n){
                double X = v[j].x;
                double Y = v[j].y;
                s.push_back(rx * (sx-X) + ry*(sy-Y));
            }
            sort(s.begin(),s.end());
            bool ng = 0;
            rep(j,n){
                if(abs(s[j]+s[n-1-j])>0.00000001){
                    ng = 1;
                }
            }
            if(!ng){
                res.push_back(MP(rx,ry));
            }
        }
    }else{
        rep(i,n){
            point a = v[i];
            long double mx = a.x;
            long double my = a.y;
            long double rx = (mx-sx);
            long double ry = (my-sy);
            swap(rx,ry);
            ry = -ry;
            long double d = sqrt(rx*rx+ry*ry);
            rx /= d;
            ry /= d;
            if(rx<0){
                rx = -rx;
                ry = -ry;
            }
            vector<long double> s;
            rep(j,n){
                double X = v[j].x;
                double Y = v[j].y;
                s.push_back(rx * (sx-X) + ry*(sy-Y));
            }
            sort(s.begin(),s.end());
            bool ng = 0;
            rep(j,n){
                if(abs(s[j]+s[n-1-j])>0.00000001){
                    ng = 1;
                }
            }
            if(!ng){
                res.push_back(MP(rx,ry));
            }
        }
    }
    int m = res.size();
    int sm = m;
    rep(i,m-1){
        if(abs(res[i].first-res[i+1].first)<=0.0000001&&abs(res[i].second-res[i+1].second)<=0.0000001){
            sm--;
        }
    }
    if(sm<=3){
        if(n!=3)assert(0);
        cout << sm << endl;
    }else{
        cout << -1 << endl;
    }
    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 < n; ++j) {
        vals[j] = origx[j] * mdx + origy[j] * mdy;
    }

    sort(vals, vals + n);

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

    for (int j = 0; j < n - 1 - j; ++j) {
        if (vals[j] + vals[n - 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";
}

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 2010
#define vector point
#define double long double
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
const double eps=1E-11;
const double PI=3.1415926535897932;
int n,ans;
double b[N];
bool flag[N];
struct point{
	double x,y;
	vector operator +(const vector&a) const
	{
		return (vector){x+a.x,y+a.y};
	}
	vector operator -(const vector&a) const
	{
		return (vector){x-a.x,y-a.y};
	}
	vector operator *(const double&a) const
	{
		return (vector){a*x,a*y};
	}
	double operator *(const vector&a) const
	{
		return x*a.y-y*a.x;
	}
	double operator ^(const vector&a) const
	{
		return x*a.x+y*a.y;
	}
	double len(){return sqrt(x*x+y*y);}
	bool iszero(){return len()<eps;}
	vector rotate(double alpha){return (vector){x*cos(alpha)+y*sin(alpha),x*sin(alpha)-y*cos(alpha)};}
}a[N],c[N],P;
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("d.in","r",stdin);
	freopen("d.out","w",stdout);
#endif
	n=read();
	for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),P=P+a[i];
	P=P*(1.0/n);int cnt=0,t=0;
	for (int i=1;i<=n;i++)
		for (int j=1;j<i;j++)
		if ((a[i]+a[j]-P*2).iszero()) {flag[i]=flag[j]=1;break;}
	for (int i=1;i<=n;i++) if (!flag[i]) a[++t]=a[i];
	n=t;t=0;if (!n) {cout<<-1;return 0;}
	for (int i=1;i<=n;i++)
	{
		vector Q=(a[i]+a[1])*0.5-P;
		double w=Q.len();
		if (fabs(w)<eps) {cnt++;continue;}
		w=1.0/w;Q=Q*w;
		for (int j=1;j<=n;j++) b[j]=a[j]*Q;
		sort(b+1,b+n+1);
		bool flag=0;double mid=P*Q;
		for (int j=1;j<=n;j++) if (fabs(b[j]+b[n-j+1]-mid*2)>eps) {flag=1;break;}
		if (!flag) c[++t]=Q;
	}
	for (int i=1;i<=t;i++)
	{
		flag[i]=1;
		for (int j=1;j<i;j++)
		if (flag[j]&&fabs(c[i]*c[j])<eps) {flag[i]=0;break;}
		if (flag[i]) ans++;
	}
	cout<<ans;
	return 0;
	//NOTICE LONG LONG!!!!!
}

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=2010;
const double eps=1e-6;

struct point {
	double x,y;
	point () {}
	point (double x,double y):x(x),y(y) {}
	point operator + (const point &P) const {
		return point(x+P.x,y+P.y);
	}
	point operator - (const point &P) const {
		return point(x-P.x,y-P.y);
	}
	point operator * (const double &T) const {
		return point(x*T,y*T);
	}
} p[N],q[N],h;

struct line {
	point p;
	int a,b;
	double k;
	bool operator < (const line &L) const {
		return k<L.k;
	}
} L[N*N];

int n,tmp,cnt,ans;
double x,y;
bool vis[N];

inline double cross(point A,point B) {return A.x*B.y-B.x*A.y;}
inline double dot(point A,point B) {return A.x*B.x+A.y*B.y;}
inline double len(point A) {return sqrt(dot(A,A));}
inline int judge(double x) {return fabs(x)<eps?0:(x>0?1:-1);}

int main() {
	scanf("%d",&n);
	for (int i=1; i<=n; i++) scanf("%lf%lf",&q[i].x,&q[i].y),h=h+q[i];
	h=h*(1.0/n);
	for (int i=1; i<n; i++) for (int j=i+1; j<=n; j++)
		if (!judge(cross(q[i],q[j])) && !judge(len(q[i])-len(q[j]))) vis[i]=vis[j]=1;
	for (int i=1; i<=n; i++) if (!vis[i]) p[++tmp]=q[i]; n=tmp;
	if (tmp<=2) {puts("-1"); return 0;}
	for (int i=1; i<n; i++) for (int j=i+1; j<=n; j++) {
		x=p[i].x+p[j].x-h.x*2; y=p[i].y+p[j].y-h.y*2; ++cnt;
		L[cnt].p=point(y,-x); L[cnt].a=i; L[cnt].b=j; L[cnt].k=atan2(-x,y);
	}
	sort(L+1,L+cnt+1);
	for (int l=1,r=0; l<=cnt; l=r+1) {
		while (r<cnt && !judge(cross(L[l].p,L[r+1].p))) r++;
		if (r-l+1<n/2) continue;
		memset(vis,0,sizeof vis);
		for (int i=l; i<=r; i++) if (!vis[L[i].a]&&!vis[L[i].b]) vis[L[i].a]=vis[L[i].b]=1;
		int cnt=0,id;
		for (int i=1; i<=n; i++) if (!vis[i]) ++cnt,id=i;
		if ((cnt>0&&!(n&1))||((cnt>1)&&(n&1))) continue;
		if (!cnt||!judge(dot(p[id]-h,L[l].p))) ans++;
	}
	printf("%d\n",ans);
	return 0;
}

#include <bits/stdc++.h>
#define fr(a, b, c) for(int a = b; a < (int) c; ++a)
using namespace std;
typedef pair<int, int> ii;

const double INF = 1e100;
const double EPS = 1e-9;
const double PI = acos(-1.0);

int cmp(double a, double b = 0.0) {
  if (fabs(a-b) < EPS) return 0;
  else if (a < b) return -1;
  return 1;
}

struct PT {
  double x,y;
  PT() {}
  PT(double x, double y) : x(x), y(y){}
  PT(const PT &p) : x(p.x), y(p.y){}
  PT operator +(const PT &p)     const { return PT(x+p.x,y+p.y); }
  PT operator -(const PT &p)     const { return PT(x-p.x,y-p.y); }
  PT operator *(double c)        const { return PT(x*c,y*c);     }
  PT operator /(double c)        const { return PT(x/c,y/c);     }
  double operator *(const PT &p) const { return x*p.x+y*p.y;     }
  double operator %(const PT &p) const { return x*p.y-y*p.x;     }
  double operator !()            const { return sqrt(x*x+y*y);   }
  double operator ^(const PT &p) const { return (atan2(*this%p,*this*p)); }
  bool operator ==(const PT &p)  const { return cmp(x,p.x)==0 && cmp(y,p.y)==0; }
  bool operator <(const PT &p)   const {
    if (cmp(x,p.x)!=0) return cmp(x,p.x)==-1;
    return cmp(y,p.y)==-1;
  }
};

ostream &operator<<(ostream &os, const PT &p) {
  os << "(" << p.x << "," << p.y << ")";
}

// roda o ponto CCW ou CW ao redor da origem
PT rotateCCW90(PT p) { return PT(-p.y,p.x); }
PT rotateCW90(PT p)  { return PT(p.y,-p.x); }
PT rotateCCW(PT p, double t) {
  return PT(p.x * cos(t) - p.y * sin(t), p.x * sin(t) + p.y * cos(t));
}

// projeta ponto c na linha através de a e b
// assume a != b
PT projPtLine(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  return a + b * (c*b) / (b*b);
}

// projeta ponto c no segmento através de a e b
PT projPtSeg(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  double r = b * b;
  if (cmp(r) == 0) return a;
  r = c * b / r;
  if (r < 0) return a;
  if (r > 1) return a+b;
  return a + b * r;
}

bool azul[12345];

int main() {
    ios::sync_with_stdio(0);
    int n;
    cin >> n;
    vector<PT> pts;
    PT cent(0,0);
    fr(i, 0, n) {
        int a, b;
        cin >> a >> b;
        pts.push_back(PT(a, b));
        cent = cent + PT(a, b);
    }
    cent = cent / n;
    vector<PT> r_pts;
    fr(i, 0, n) {
        if(pts[i] == cent) {
            azul[i] = true;
        }
        fr(j, i + 1, n) {
            if(!azul[i] && !azul[j] && (pts[i] + pts[j]) / 2 == cent) {
                azul[i] = azul[j] = true;
            }
        }
    }
    fr(i, 0, n) {
        if(!azul[i]) {
            r_pts.push_back(pts[i]);
        }
    }
    pts = r_pts;
    n = pts.size();
    if(n == 0) {
        cout << -1 << endl;
        return 0;
    }
    PT a = pts[0];
    bool inf = true;
    int res = 0;
    vector<double> angles;
    fr(i, 0, n) {
        PT b = pts[i];
        PT media = (a + b) / 2;
        PT vec = (media - cent);
        if(vec == PT(0,0)) {
            continue;
        }
        if(i) inf = false;
        PT perp = rotateCCW90(vec);
        PT cent_proj = projPtLine(PT(0, 0), perp, cent);

        double angle = PT(1, 0) ^ perp;
        if(cmp(angle) < 0) angle += PI;
        bool continua = false;
        for(auto a : angles) {
            if(cmp(angle, a) == 0) {
                continua = true;
                break;
            }
        }
        angles.push_back(angle);
        if(continua) continue;

        vector<double> dists;
        fr(i, 0, n) {
            PT proj = projPtLine(PT(0, 0), perp, pts[i]);

            double prod_scalar = (perp - PT(0,0)) * (proj - cent_proj);
            int sign = cmp(prod_scalar, 0);
            if(sign == 0) continue;
            dists.push_back(!(proj - cent_proj) * sign);
        }
        sort(dists.begin(), dists.end());

        bool ok = true;
        fr(i, 0, dists.size()) {
            if(cmp(dists[i] + dists[dists.size() - i - 1]) != 0) {
                ok = false;
                break;
            }
        }
        if(ok) ++res;
    }
    if(inf)
        cout << -1 << endl;
    else
        cout << res << endl;
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define sqr(x) ((x)*(x))
#define mp make_pair
#define uint unsigned
#define PI pair<ll,ll>
#define fi first
#define se second
#define ld long double
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 ll read(){
	ll x = 0; char ch = gc(); bool positive = 1;
	for (; !isdigit(ch); ch = gc())	if (ch == '-')	positive = 0;
	for (; isdigit(ch); ch = gc())	x = x * 10 + ch - '0';
	return positive ? x : -x;
}
inline void write(ll a){
    if(a<0){
    	a=-a; putchar('-');
	}
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
inline void writeln(ll a){write(a); putchar('\n');}
inline void wri(ll a){write(a); putchar(' ');}
const int N=100005;
int x[N],y[N],lx,ly,Ans;
set<pair<int,int> > M;
ll q[N];
PI ans[N];
bool vis[N];
int main(){
	//freopen("akitomoya.in","r",stdin);freopen("akitomoya.out","w",stdout);
	int n=read();
	for(int i=1;i<=n;i++){
		x[i]=read(); y[i]=read();
	}
	int ho=0;
	if(n%2==0){
		n--; ho=1;
	}
	for(int i=1;i<=n;i++){
		ll tx=ho?x[i]+x[n+1]:x[i]*2,ty=ho?y[i]+y[n+1]:y[i]*2;
		if(M.count(mp(tx,ty)))continue; else M.insert(mp(tx,ty));
		ll sumx=0,sumy=0;
		for(int j=1;j<=n;j++)if(i!=j){sumx+=x[j]; sumy+=y[j];}
		//cout<<tx<<" "<<ty<<" "<<sumx<<" "<<sumy<<endl;
		if(sumx!=tx*((n-1)/2)||sumy!=ty*((n-1)/2)){//cout<<i<<" pt"<<endl;
			ll S=ty*(n-1)/2-sumy,T=sumx-tx*(n-1)/2; *q=0;
			for(int j=1;j<=n;j++)if(i!=j)q[++*q]=(x[j])*S+(y[j])*T;
			sort(&q[1],&q[*q+1]);
			int f=1;
			ll t=tx*S+ty*T;
			for(int j=1;j<=*q/2&&f;j++)if(q[j]+q[*q-j+1]!=t)f=0;
			//cout<<f<<" "<<i<<" "<<S<<" "<<T<<" "<<t<<endl;
			if(f)ans[Ans++]=mp(S,T);
		}else{//cout<<i<<endl;
			int fff=1;
			for(int j=1;j<=n;j++)if(i!=j&&!vis[j]){
				int f=1;
				for(int k=j+1;k<=n&&f;k++)if(i!=k&&x[k]+x[j]==tx&&y[k]+y[j]==ty&&!vis[k]){
					vis[k]=vis[j]=1; f=0;
				}
				if(f){//cout<<i<<" "<<j<<" "<<f<<endl;
					fff=0;
					for(int k=j;k<=n;k++)if(!vis[k]){
						ll S=y[j]+y[k]-ty,T=tx-x[j]-x[k]; *q=0;

						for(int l=j;l<=n;l++)if(!vis[l]){
							q[++*q]=S*x[l]+T*y[l];
						}
						sort(&q[1],&q[*q+1]);

						ll t=tx*S+ty*T;
						int f=1;
						for(int j=1;j<=*q/2&&f;j++)if(q[j]+q[*q-j+1]!=t)f=0; //cout<<f<<" "<<j<<" "<<k<<" "<<S<<" "<<T<<endl;
						if(f)ans[Ans++]=mp(S,T);
					}
					break;
				}
			}
			if(fff){
				puts("-1"); return 0;
			}
		}
	}
	int tot=0;
	for(int i=0;i<Ans;i++){
		int f=1;
		for(int j=0;j<i&&f;j++)if(ans[i].fi*ans[j].se==ans[i].se*ans[j].fi)f=0;
		tot+=f;
		//cout<<i<<" "<<ans[i].fi<<" "<<ans[i].se<<endl;
		//for(int j=1;j<=n;j++)cout<<ans[i].fi*x[j]+ans[i].se*y[j]<<endl;
	}
	cout<<tot<<endl;
}
/*
7
0 0
2 2
1 -1
-1 2
-2 -1
4 4
-4 -5
6 6
-6 -7
*/

#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define fi first
#define se second
using namespace std;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int,int> ii;
typedef pair<double,double> dd;
typedef pair<char,char> cc;
typedef vector<ii> vii;
typedef long long ll;
typedef pair<ll, ll> l4;
typedef long double ld;
typedef pair<ld,ld> ldd;
const ld pi = acosl(-1);
const int maxn = 2010;
const ll mod = 1e9+7;
const int inf = 1e9;
const ld eps = 1e-8;

int n;
int x[maxn],y[maxn];
int gone[maxn];
ld X,Y;
vector<ldd> ans;
int dcmp(ld x) {
    if (x > eps) return 1;
    if (x < -eps) return -1;
    return 0;
}

bool check(ld dx, ld dy) {
    ld len = sqrt(dx*dx+dy*dy);
    dx /= len, dy /= len;
    vector<ld> vec;
    rep(i, 0, n) if (!gone[i]) {
        vec.push_back(x[i]*dx+y[i]*dy);
    }
    sort(vec.begin(),vec.end());
    ld c = X*dx+Y*dy;
    int half = vec.size()/2;
    int Size = vec.size()-1;
    rep(i, 0, half) if (dcmp(vec[i]+vec[Size-i]-2*c)) {
        return 0;
    }
    Size++;
    if (half*2 < Size && dcmp(vec[half]-c)) return 0;
    if (dx < 0) dx = -dx, dy = -dy;
    ans.push_back({dx,dy});
    return 1;
}

int main() {
    scanf("%d",&n);
    rep(i, 0, n) scanf("%d%d",&x[i],&y[i]),
    X += x[i], Y += y[i];
    X /= n, Y /= n;
    int num = n;
    rep(i, 0, n) rep(j, i+1, n) {
        if (!gone[i] && dcmp(x[i]-X)==0 && dcmp(y[i]-Y)==0) {
            gone[i] = 1;
            num--;
        }
        if (gone[i] || gone[j]) continue;
        if (dcmp(x[i]+x[j]-2*X)==0 && dcmp(y[i]+y[j]-2*Y)==0) {
            gone[i] = gone[j] = 1;
            num -= 2;
        }
    }
    if (num <= 1) {
        printf("-1\n");
        return 0;
    }

    if (num&1) {
        rep(i, 0, n) if (!gone[i]) {
            ld dx = x[i]-X, dy = y[i]-Y;
            check(-dy,dx);
        }
    } else {
        int j = 0;
        while (gone[j]) j++;
        rep(i, j+1, n) if (!gone[i]) {
            ld midx = (ld)(x[i]+x[j])/2;
            ld midy = (ld)(y[i]+y[j])/2;
            ld dx = midx-X, dy = midy-Y;
            check(-dy,dx);
        }
    }
    int cnt = 0;
    rep(i, 0, ans.size()) {
        bool ok = 1;
        rep(j, 0, i) {
            if (dcmp(ans[i].fi-ans[j].fi) == 0
                && dcmp(ans[i].se-ans[j].se) == 0) {
                ok = 0;
                break;
            }
        }
        cnt += ok;
    }
    printf("%d",cnt);
    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-6
//#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,5){
		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<cstdio>
#include<algorithm>
#include<map>
using namespace std;
int n, res;
struct point {
	long long x, y;
	point operator + (const point &p)const {
		return { x + p.x, y + p.y };
	}
	point operator - (const point &p)const {
		return { x - p.x, y - p.y };
	}
	point operator *(const int &k)const {
		return { x*k,y*k };
	}
	point operator /(const int &k)const {
		return { x/k,y/k };
	}
	bool operator ==(const point &p)const {
		return x == p.x && y == p.y;
	}
	bool operator<(const point &p)const {
		return x != p.x ? x < p.x : y < p.y;
	}
	point Rotate() {
		return { y,-x };
	}
}w[2010], M, tw[2010];
map<point, int>Map;
int chk1[2010][2010], chk2[2010], tn, nn;
long long ccw(point a, point b, point c) {
	return (b.x - a.x)/nn*(c.y - a.y) - (b.y - a.y)/nn*(c.x - a.x);
}
long long U[2010];
long long gcd(long long a, long long b) {
	return b ? gcd(b, a%b) : a;
}
void Make(point &a) {
	if (a.x < 0 || (a.x == 0 && a.y < 0)) {
		a.x = -a.x;
		a.y = -a.y;
	}
	long long g = gcd(abs(a.x), abs(a.y));
	a.x /= g, a.y /= g;
}
int main() {
	int i, j;
	scanf("%d", &n);
	nn = n;
	for (i = 1; i <= n; i++) {
		scanf("%lld%lld", &w[i].x, &w[i].y);
		w[i].x *= 2, w[i].y *= 2;
		M.x += w[i].x, M.y += w[i].y;
		w[i].x *= n, w[i].y *= n;
	}
	for (i = 1; i <= n; i++) {
		if (w[i] == M)continue;
		tw[++tn] = w[i];
	}
	n = tn;
	for (i = 1; i <= tn; i++)w[i] = tw[i];
	int cc = 0;
	for (i = 1; i <= n; i++)for (j = 1; j <= n; j++) {
		if (w[i] + w[j] == M * 2)cc++;
	}
	if (cc == n) {
		printf("-1\n");
		return 0;
	}
	for (i = 1; i <= 1; i++) {
		for (j = i+1; j <= n; j++) {
			if (ccw(w[i], w[j], M) == 0) continue;
			else {
				point MM = (w[i] + w[j]) / 2;
				point tp = (MM - M).Rotate();
				Make(tp);
				Map[tp]++;
				tp = tp.Rotate();
				Make(tp);
				Map[tp]++;
			}
		}
		point tp = (w[i] - M).Rotate();
		Make(tp);
		Map[tp]++;
		tp = tp.Rotate();
		Make(tp);
		Map[tp]++;
	}
	for (auto &tp : Map) {
		point a = tp.first;
		for (i = 1; i <= n; i++) {
			U[i] = w[i].x / nn * a.x + w[i].y / nn * a.y;
		}
		sort(U + 1, U + n + 1);
		int chk = 0;
		for (i = 1; i <= n; i++) {
			if (U[i] + U[n + 1 - i] != U[1] + U[n])chk = 1;
		}
		if (!chk)res++;
	}
	printf("%d\n", res);
}

#pragma GCC optimize ("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")
#include <bits/stdc++.h>
#define fr(a, b, c) for(int a = b; a < (int) c; ++a)
using namespace std;
typedef pair<int, int> ii;

const long double INF = 1e100;
const long double EPS = 1e-10;
const long double PI = acos(-1.0);

int cmp(long double a, long double b = 0.0) {
  if (fabs(a-b) < EPS) return 0;
  else if (a < b) return -1;
  return 1;
}

struct PT {
  long double x,y;
  PT() {}
  PT(long double x, long double y) : x(x), y(y){}
  PT(const PT &p) : x(p.x), y(p.y){}
  PT operator +(const PT &p)     const { return PT(x+p.x,y+p.y); }
  PT operator -(const PT &p)     const { return PT(x-p.x,y-p.y); }
  PT operator *(long double c)        const { return PT(x*c + 1e-15L,y*c + 1e-15L);     }
  PT operator /(long double c)        const { return PT(x/c + 1e-15L,y/c + 1e-15L);     }
  long double operator *(const PT &p) const { return x*p.x+y*p.y;     }
  long double operator %(const PT &p) const { return x*p.y-y*p.x;     }
  long double operator !()            const { return sqrt(x*x+y*y);   }
  long double operator ^(const PT &p) const { return (atan2(*this%p,*this*p)); }
  bool operator ==(const PT &p)  const { return cmp(x,p.x)==0 && cmp(y,p.y)==0; }
  bool operator <(const PT &p)   const {
    if (cmp(x,p.x)!=0) return cmp(x,p.x)==-1;
    return cmp(y,p.y)==-1;
  }
};

ostream &operator<<(ostream &os, const PT &p) {
  os << "(" << p.x << "," << p.y << ")";
}

// roda o ponto CCW ou CW ao redor da origem
PT rotateCCW90(PT p) { return PT(-p.y,p.x); }
PT rotateCW90(PT p)  { return PT(p.y,-p.x); }
PT rotateCCW(PT p, long double t) {
  return PT(p.x * cos(t) - p.y * sin(t), p.x * sin(t) + p.y * cos(t));
}

// projeta ponto c na linha através de a e b
// assume a != b
PT projPtLine(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  return a + b * (c*b) / (b*b);
}

// projeta ponto c no segmento através de a e b
PT projPtSeg(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  long double r = b * b;
  if (cmp(r) == 0) return a;
  r = c * b / r;
  if (r < 0) return a;
  if (r > 1) return a+b;
  return a + b * r;
}

bool azul[12345];

int main() {
    srand(time(NULL));
    ios::sync_with_stdio(0);
    int n;
    cin >> n;
    vector<PT> pts;
    PT cent(0,0);
    fr(i, 0, n) {
        int a, b;
        cin >> a >> b;
        pts.push_back(PT(a, b));
        cent = cent + PT(a, b);
    }
    cent = cent / n;
    vector<PT> r_pts;
    fr(i, 0, n) {
        if(pts[i] == cent) {
            azul[i] = true;
        }
        fr(j, i + 1, n) {
            if(!azul[i] && !azul[j] && (pts[i] + pts[j]) / 2 == cent) {
                azul[i] = azul[j] = true;
            }
        }
    }
    fr(i, 0, n) {
        if(!azul[i]) {
            r_pts.push_back(pts[i]);
        }
    }
    pts = r_pts;
    n = pts.size();
    if(n == 0) {
        cout << -1 << endl;
        return 0;
    }

    int ans = 1e9;

    fr(kk, 0, min(4, n)) {
        vector<long double> angles;
        int res = 0;
        int bicho = rand() % n;
        PT a = pts[bicho];
        fr(i, 0, n) {
            PT b = pts[i];
            PT media = (a + b) / 2;
            PT vec = (media - cent);
            PT perp = rotateCCW90(vec);
            PT cent_proj = projPtLine(PT(0, 0), perp, cent);

            long double angle = PT(1, 0) ^ perp;
            if(cmp(angle) < 0) angle += PI;
            bool continua = false;
            for(auto a : angles) {
                if(cmp(angle, a) == 0) {
                    continua = true;
                    break;
                }
            }
            angles.push_back(angle);
            if(continua) continue;

            vector<long double> dists;
            fr(i, 0, n) {
                PT proj = projPtLine(PT(0, 0), perp, pts[i]);

                long double prod_scalar = (perp) * (proj - cent_proj) + 1e-15L;
                int sign = cmp(prod_scalar, 0);
                if(sign == 0) sign = 1;
                if (cmp(!(proj - cent_proj)) == 0) continue;
                dists.push_back(!(proj - cent_proj) * sign);
            }
            sort(dists.begin(), dists.end());

            bool ok = true;
            fr(i, 0, dists.size()) {
                if(cmp(dists[i] + dists[dists.size() - i - 1]) != 0) {
                    ok = false;
                    break;
                }
            }
            if(ok) ++res;
        }
        ans = min(ans, res);
    }

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

#include <bits/stdc++.h>
using namespace std;
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge {c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

typedef long long ll;
struct P {
	ll x, y;
	void read() {
		scanf("%lld%lld", &x, &y);
	}
	P operator - (const P & he) const {
		return P{x - he.x, y - he.y};
	}
	P operator + (const P & he) const {
		return P{x + he.x, y + he.y};
	}
	P operator * (ll mul) const {
		return P{x * mul, y * mul};
	}
	P operator / (ll mul) const {
		assert(x % mul == 0 && y % mul == 0);
		return P{x / mul, y / mul};
	}
	ll operator *(const P & he) const {
		return x * he.y - y * he.x;
	}
	bool operator == (const P & he) const {
		return x == he.x && y == he.y;
	}
};

int main() {
	int n;
	scanf("%d", &n);
	vector<P> points(n);
	P mid = {0, 0};
	for(P & p : points) {
		p.read();
		p = p * 2;
		mid = mid + p;
		p = p * n;
	}
	vector<bool> vis(n);
	for(int i = 0; i < (int) points.size(); ++i)
		if(!vis[i]) {
			if(points[i] == mid) {
				vis[i] = true;
				continue;
			}
			for(int j = i + 1; j < (int) points.size(); ++j)
				if(!vis[j] && (points[i] - mid) == (mid - points[j])) {
					vis[i] = vis[j] = true;
					break;
				}
		}
	vector<P> nowe;
	for(int i = 0; i < n; ++i)
		if(!vis[i])
			nowe.push_back(points[i]);
	points = nowe;
	n = points.size();
	debug() << imie(n);
	if(n <= 1) {
		puts("-1");
		return 0;
	}
	int answer = 0;
	vector<P> already;
	for(int i = 0; i < n; ++i) {
		P he = (points[0] + points[i]) / 2;
		debug() << imie(i) imie(he.x) imie(he.y);
		assert(!(he == mid));
		bool ok = true;
		for(const P & p : already) if((p - mid) * (he - mid) == 0) {
			ok = false;
			break;
		}
		if(!ok) continue;
		vector<ll> values;
		for(const P & p : points)
			values.push_back((p - mid) * (he - mid));
		sort(values.begin(), values.end());
		ll should = values[0] + values.back();
		for(int j = 0; j < n; ++j)
			if(values[j] + values[n-1-j] != should) {
				ok = false;
				break;
			}
		if(ok) ++answer;
	}
	printf("%d\n", answer);
}

#include<bits/stdc++.h>
using namespace std;
#define REP(i,st,ed) for(register int i=st,i##end=ed;i<=i##end;++i)
#define DREP(i,st,ed) for(register int i=st,i##end=ed;i>=i##end;--i)
typedef long long ll;
template<typename T>inline bool chkmin(T &x,T y){return (y<x)?(x=y,1):0;}
template<typename T>inline bool chkmax(T &x,T y){return (y>x)?(x=y,1):0;}
inline int read(){
	int x;
	char c;
	int f=1;
	while((c=getchar())!='-' && (c>'9' || c<'0'));
	if(c=='-') f=-1,c=getchar();
	x=c^'0';
	while((c=getchar())>='0' && c<='9') x=(x<<1)+(x<<3)+(c^'0');
	return x*f;
}
inline ll readll(){
	ll x;
	char c;
	int f=1;
	while((c=getchar())!='-' && (c>'9' || c<'0'));
	if(c=='-') f=-1,c=getchar();
	x=c^'0';
	while((c=getchar())>='0' && c<='9') x=(x<<1ll)+(x<<3ll)+(c^'0');
	return x*f;
}
const int maxn=1000+10;
const long double eps=(1e-9);
struct point{
	long double x,y;
	point operator +(const point &rhs) const{
		return (point){x+rhs.x,y+rhs.y};
	}
	point operator -(const point &rhs) const{
		return (point){x-rhs.x,y-rhs.y};
	}
	point operator /(const int &rhs) const{
		return (point){x/rhs,y/rhs};
	}
	bool operator ==(const point &rhs) const{
		return fabs(x-rhs.x)<=eps && fabs(y-rhs.y)<=eps;
	}
	double operator *(const point &rhs) const{
		return x*rhs.x+y*rhs.y;
	}
	void clear(){
		x=y=0;
	}
}a[maxn],rt,ve;
double p[maxn];
int n,ans,st,id[maxn];
bool cmp(const int A,const int B){
	return p[A]<p[B];
}
inline void get_ans(int x){
	ve=(a[x]+a[st])/2;
	ve=rt-ve;
	ve=(point){ve.y,-ve.x};
	REP(i,1,n) id[i]=i,p[i]=ve*a[i];
	sort(id+1,id+n+1,cmp);
	double num=p[id[1]]+p[id[n]];
	int u=0;
	REP(i,1,n){
		if(id[i]==x) u+=i;
		if(id[i]==st) u+=i;
	}
	if(u!=n+1) return;
	REP(i,1,(n+1)>>1) if(fabs(num-p[id[i]]-p[id[n+1-i]])>eps) return;
	++ans;
}
inline void work(){
	ans=0;
	rt.clear();
	n=read();
	REP(i,1,n) a[i].x=read(),a[i].y=read(),rt=rt+a[i];
	rt=rt/n;
	st=0;
	REP(i,1,n){
		bool flag=1;
		REP(j,1,n) if((a[i]+a[j])/2==rt){
			flag=0;
			break;
		}
		if(flag) st=i;
	}
	if(!st){
		printf("-1\n");
		return;
	}
	REP(i,1,n) get_ans(i);
	printf("%d\n",ans);
}
int main(){
	work();
	return 0;
}

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
#define N 2010
using namespace std;
const double eps = 1e-9;
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], ans;
double len[N];
bool d[N];
bool cmp1(int x, int y)
{
    return len[x] < len[y];
}
bool cmp2(node x, node y)
{
    return (x - M) * (y - M) < 0;
}
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;

    // cout << "c:" << M.x << ' ' << M.y << endl;
    // for (int i = 1; i <= n; i++)
    //     cout << a[i].x << ',' << a[i].y << ' ';
    // puts("");
    for (int i = 1; i <= n; i++)
        b[i] = mid(a[i], a[1]);
    sort(b + 1, b + n + 1, cmp2);
    node v;
    for (int i = 1, j; i <= n; i++)
    {
        if (i > 1 && fabs(v * (M - b[i])) < eps)
            continue;
        v = M - b[i];
        // cout << "v:" << v.x << ' ' << v.y << endl;
        for (int j = 1; j <= n; j++)
            len[j] = v * (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;
            }
        ans += ok;
    }
    printf("%d", ans);
    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>
#define fr(a, b, c) for(int a = b; a < (int) c; ++a)
using namespace std;
typedef pair<int, int> ii;

const long double INF = 1e100;
const long double EPS = 1e-10;
const long double PI = acos(-1.0);

int cmp(long double a, long double b = 0.0) {
  if (fabs(a-b) < EPS) return 0;
  else if (a < b) return -1;
  return 1;
}

struct PT {
  long double x,y;
  PT() {}
  PT(long double x, long double y) : x(x), y(y){}
  PT(const PT &p) : x(p.x), y(p.y){}
  PT operator +(const PT &p)     const { return PT(x+p.x,y+p.y); }
  PT operator -(const PT &p)     const { return PT(x-p.x,y-p.y); }
  PT operator *(long double c)        const { return PT(x*c,y*c);     }
  PT operator /(long double c)        const { return PT(x/c,y/c);     }
  long double operator *(const PT &p) const { return x*p.x+y*p.y;     }
  long double operator %(const PT &p) const { return x*p.y-y*p.x;     }
  long double operator !()            const { return x*x+y*y;   }
  long double operator ^(const PT &p) const { return (atan2(*this%p,*this*p)); }
  bool operator ==(const PT &p)  const { return cmp(x,p.x)==0 && cmp(y,p.y)==0; }
  bool operator <(const PT &p)   const {
    if (cmp(x,p.x)!=0) return cmp(x,p.x)==-1;
    return cmp(y,p.y)==-1;
  }
};

ostream &operator<<(ostream &os, const PT &p) {
  os << "(" << p.x << "," << p.y << ")";
}

// roda o ponto CCW ou CW ao redor da origem
PT rotateCCW90(PT p) { return PT(-p.y,p.x); }
PT rotateCW90(PT p)  { return PT(p.y,-p.x); }
PT rotateCCW(PT p, long double t) {
  return PT(p.x * cos(t) - p.y * sin(t), p.x * sin(t) + p.y * cos(t));
}

// projeta ponto c na linha através de a e b
// assume a != b
PT projPtLine(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  return a + b * (c*b) / (b*b);
}

// projeta ponto c no segmento através de a e b
PT projPtSeg(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  long double r = b * b;
  if (cmp(r) == 0) return a;
  r = c * b / r;
  if (r < 0) return a;
  if (r > 1) return a+b;
  return a + b * r;
}

bool azul[12345];

int main() {
    srand(time(NULL));
    ios::sync_with_stdio(0);
    int n;
    cin >> n;
    vector<PT> pts;
    PT cent(0,0);
    fr(i, 0, n) {
        int a, b;
        cin >> a >> b;
        pts.push_back(PT(a, b));
        cent = cent + PT(a, b);
    }
    cent = cent / n;
    vector<PT> r_pts;
    fr(i, 0, n) {
        if(pts[i] == cent) {
            azul[i] = true;
        }
        fr(j, i + 1, n) {
            if(!azul[i] && !azul[j] && (pts[i] + pts[j]) / 2 == cent) {
                azul[i] = azul[j] = true;
            }
        }
    }
    fr(i, 0, n) {
        if(!azul[i]) {
            r_pts.push_back(pts[i]);
        }
    }
    pts = r_pts;
    n = pts.size();
    if(n == 0) {
        cout << -1 << endl;
        return 0;
    }

    int ans = 1e9;

    fr(kk, 0, min(3, n)) {
        vector<long double> angles;
        int res = 0;
        int bicho = rand() % n;
        PT a = pts[bicho];
        fr(i, 0, n) {
            PT b = pts[i];
            PT media = (a + b) / 2;
            PT vec = (media - cent);
            PT perp = rotateCCW90(vec);

            long double angle = PT(1, 0) ^ perp;
            if(cmp(angle) < 0) angle += PI;
            bool continua = false;
            for(auto a : angles) {
                if(cmp(angle, a) == 0) {
                    continua = true;
                    break;
                }
            }
            angles.push_back(angle);
            if(continua) continue;

            vector<long double> dists;
            fr(i, 0, n) {
                PT proj = projPtLine(cent, cent + perp, pts[i]);

                int sign = proj < cent ? 1 : -1;

                if (cmp(!(proj - cent)) == 0) continue;
                dists.push_back(!(proj - cent) * sign);
            }
            sort(dists.begin(), dists.end());

            bool ok = true;
            fr(i, 0, dists.size()) {
                if(cmp(dists[i] + dists[dists.size() - i - 1]) != 0) {
                    ok = false;
                    break;
                }
            }
            if(ok) ++res;
        }
        ans = min(ans, res);
    }

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

#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
int n, res;
struct point {
	long long x, y;
	point operator + (const point &p)const {
		return { x + p.x, y + p.y };
	}
	point operator - (const point &p)const {
		return { x - p.x, y - p.y };
	}
	point operator *(const int &k)const {
		return { x*k,y*k };
	}
	point operator /(const int &k)const {
		return { x/k,y/k };
	}
	bool operator ==(const point &p)const {
		return x == p.x && y == p.y;
	}
	bool operator<(const point &p)const {
		return x != p.x ? x < p.x : y < p.y;
	}
	point Rotate() {
		return { y,-x };
	}
}w[2010], M, tw[2010];
map<point, int>Map;
int chk1[2010][2010], chk2[2010], tn;
long long ccw(point a, point b, point c) {
	return (b.x - a.x)/n*(c.y - a.y) - (b.y - a.y)/n*(c.x - a.x);
}
long long U[2010];
long long gcd(long long a, long long b) {
	return b ? gcd(b, a%b) : a;
}
void Make(point &a) {
	if (a.x < 0 || (a.x == 0 && a.y < 0)) {
		a.x = -a.x;
		a.y = -a.y;
	}
	long long g = gcd(abs(a.x), abs(a.y));
	a.x /= g, a.y /= g;
}
int main() {
	int i, j, ckk = 0;
	scanf("%d", &n);
	for (i = 1; i <= n; i++) {
		scanf("%lld%lld", &w[i].x, &w[i].y);
		w[i].x *= 2, w[i].y *= 2;
		M.x += w[i].x, M.y += w[i].y;
		w[i].x *= n, w[i].y *= n;
	}
	for (i = 1; i <= n; i++) {
		if (w[i] == M)continue;
		tw[++tn] = w[i];
	}
	n = tn;
	for (i = 1; i <= tn; i++)w[i] = tw[i];
	if (!n) {
		printf("-1\n");
		return 0;
	}
	for (i = 1; i <= n; i++) {
		for (j = i+1; j <= n; j++) {
			if (ccw(w[i], w[j], M) == 0) continue;
			else {
				ckk = 1;
				point MM = (w[i] + w[j]) / 2;
				point tp = (MM - M).Rotate();
				Make(tp);
				Map[tp]++;
			}
		}
		point tp = (w[i] - M).Rotate();
		Make(tp);
		Map[tp]++;
	}
	if (!ckk) {
		sort(w + 1, w + n + 1);
		ckk = 0;
		for (i = 1; i <= n; i++) {
			if (w[i] + w[n + 1 - i] == M * 2)ckk++;
		}
		if (ckk == n) {
			printf("-1\n");
		}
		else printf("0\n");
		return 0;
	}
	for (auto &tp : Map) {
		if (tp.second * 2 < n - 10)continue;
		point a = tp.first;
		for (i = 1; i <= n; i++) {
			U[i] = w[i].x / n * a.x + w[i].y / n * a.y;
		}
		sort(U + 1, U + n + 1);
		int chk = 0;
		for (i = 1; i <= n; i++) {
			if (U[i] + U[n + 1 - i] != U[1] + U[n])chk = 1;
		}
		if (!chk)res++;
	}
	printf("%d\n", res);
}

/*input
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;
typedef long long ll;
typedef long double ld;
struct point
{
	ll x, y;
	point(): x(0), y(0)
	{

	}
	point(ll x, ll y): x(x), y(y)
	{

	}
	bool operator<(const point &o)const
	{
		if (x != o.x)
			return x < o.x;
		return y < o.y;
	}
	void kryptis()
	{
		ll g = __gcd(abs(x), abs(y));
		x /= g;
		y /= g;
		if (y < 0 || (y == 0 && x < 0))
		{
			x *= -1;
			y *= -1;
		}
	}
};
point operator-(point a, point b)
{
	return point(a.x - b.x, a.y - b.y);
}
point operator-(point a)
{
	return point(-a.x, -a.y);
}
point operator+(point a, point b)
{
	return point(a.x + b.x, a.y + b.y);
}
point operator*(point a, ll k)
{
	return point(a.x * k, a.y * k);
}
ll cross(point a, point b)
{
	return a.y * b.x - a.x * b.y;
}
bool symm(vector<ll>&x)
{
	sort(x.begin(), x.end());
	for (ll i = 0; i < (ll)x.size(); i++)
		if (x[i] != -x[x.size() - i - 1])
			return false;
	return true;
}
int main()
{
	ios_base::sync_with_stdio(false);
	ll n;
	cin >> n;
	point A[n];
	point M;
	for (ll i = 0; i < n; i++)
	{
		cin >> A[i].x >> A[i].y;
		M = M + A[i];
		A[i] = A[i] * n;
	}
	for (ll i = 0; i < n; i++)
		A[i] = A[i] - M;
	set<point>AA;
	for (int i = 0; i < n; i++)
		AA.insert(A[i]);
	bool minus = true;
	for (int i = 0; i < n; i++)
		if (AA.count(-A[i]) == false)
			minus = false;
	if (minus)
	{
		cout << "-1\n";
		return 0;
	}
	ll ans = 0;
	map<point, set<ll>>C;
	for (ll i = 0; i < n; i++)
	{
		for (ll j = 0; j < i; j++)
		{
			point v = A[i] + A[j];
			if (v.x == 0 && v.y == 0)
				continue;
			v.kryptis();
			C[v].insert(i);
			C[v].insert(j);
		}
	}
	for (auto vs : C)
	{
		point V = vs.first;
		if (vs.second.size() != n)
			continue;
		vector<ll>xy;
		for (ll i : vs.second)
			xy.push_back(cross(V, A[i]));
		if (symm(xy))
		{
			if (symm(xy))
				ans++;
		}
	}
	cout << ans << "\n";
}

#include <bits/stdc++.h>

const int N = 2005;
const double eps = 1e-8;

int n;
inline int dcmp(double x)
{
	if (x > eps) return 1;
	if (x < -eps) return -1;
	return 0;
}

struct Point
{
	double x, y;
	Point (double x = 0, double y = 0) : x(x), y(y) {}
} G, O(0, 0);

inline Point operator+(const Point &p, const Point &q) { return Point(p.x + q.x, p.y + q.y); }
inline Point operator-(const Point &p, const Point &q) { return Point(p.x - q.x, p.y - q.y); }
inline Point operator*(const Point &p, double k) { return Point(p.x * k, p.y * k); }
inline Point operator*(double k, const Point &p) { return Point(p.x * k, p.y * k); }
inline Point operator/(const Point &p, double k) { return Point(p.x / k, p.y / k); }
inline bool operator<(const Point &p, const Point &q) { return dcmp(p.x - q.x) == 0 ? p.y < q.y - eps : p.x < q.x - eps; }
inline bool operator==(const Point &p, const Point &q) { return dcmp(p.x - q.x) == 0 && dcmp(p.y - q.y) == 0; }
inline bool operator!=(const Point &p, const Point &q) { return !(p == q); }
inline Point MidPoint(Point P, Point Q) { return (P + Q) / 2; }

struct Line
{
	Point P, Q;
	double k;
	Line (Point _P, Point _Q) : P(_P), Q(_Q)
	{
		if (Q < P) std::swap(P, Q);
		Point R = Q - P;
		k = R.y / R.x;
	}
};

inline bool operator< (const Line &a, const Line &b) { return a.k < b.k; }
inline bool operator==(const Line &a, const Line &b) { return a.k == b.k; }
inline double Dot(const Point &P, const Point &Q) { return P.x * Q.x + P.y * Q.y; }
inline double Cross(const Point &P, const Point &Q) { return P.x * Q.y - P.y * Q.x; }
inline Point Proj(const Line &l, const Point &C)
{
	Point BA = l.P - l.Q, BC = C - l.Q;
	return Dot(BC, BA) / Dot(BA, BA) * BA + l.Q;
}

inline Line Bot(const Line &l, const Point &C)
{
	Point u = l.P - C, v = l.Q - C;
	if (dcmp(Cross(u, v)) == 0)
	{
		Point P = l.P;
		if (P == C) P = l.Q;
		Point dir = P - C;
		double x = dir.x, y = dir.y;
		dir.x = -y, dir.y = x;
		return Line(C, C + dir);
	}
	else
	{
		return Line(C, Proj(l, C));
	}
}

std::vector<Point> P;
std::vector<Line> lines;

inline char nc()
{
	static char buf[1000000], *p1 = buf,*p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}

inline int read()
{
	int res = 0, neg = 1;
	char ch;
	do
	{
		ch = nc();
		if (ch == '-') neg = -1;
	} while (ch < 48 || ch > 57);
	do res = res * 10 + ch - 48, ch = nc(); while (ch >= 48 && ch <= 57);
	return res * neg;
}

int main(int, char**)
{
	n = read();
	for (int i = 0; i < n; ++i)
	{
		double x = read(), y = read();
		P.emplace_back(x, y); G = G + Point(x, y);
	}

	G = G / n;
	std::multiset<Point> pts;

	for (auto v : P) pts.insert(v);
	for (auto v : P)
	{
		if (pts.count(v) && pts.count(2 * G - v))
		{
			pts.erase(v);
			pts.erase(2 * G - v);
		}
	}

	if (pts.size() <= 2) return printf("-1"), 0;

	for (auto v : pts)
	{
		lines.emplace_back(G, MidPoint(P[0], v));
		Point M = MidPoint(P[0], v);
	}
	std::vector<Line> ans;
	for (auto tt : lines)
	{
		Line l = Bot(tt, O);
		Point Mid = 2 * Proj(l, G);
		std::multiset<Point> set; std::vector<Point> vec;
		for (auto v : pts)
		{
			Point r = Proj(l, v);
			set.insert(r); vec.push_back(r);
		}
		for (auto v : vec)
		{
			if (set.count(v) && v != Mid - v)
			{
				if (!set.count(Mid - v))
				{
					goto failed;
				}
				set.erase(Mid - v);
				set.erase(v);
			}
		}
		ans.emplace_back(l);
		failed:
			;
	}
	std::sort(ans.begin(), ans.end());
	ans.erase(std::unique(ans.begin(), ans.end()), ans.end());
	printf("%d\n", ans.size());
	return 0;
}

#include <bits/stdc++.h>
#define int long long
using namespace std;
struct dr
{
    int ch, zn;
    bool operator == (const dr& x) const {return (ch==x.ch and zn==x.zn);}
    bool operator < (const dr& x) const
    {
        if(ch!=x.ch) return ch<x.ch;
        else return zn<x.zn;
    }
};
int mo(int x)
{
    if(x<0) return -x;
    else return x;
}
void norm(dr& x)
{
    if(x.ch==0) x.zn=1;
    else if(x.zn==0) x.ch=1;
    else
    {
        if(x.zn<0)
        {
            x.ch*=-1, x.zn*=-1;
        }
        int x2=__gcd(mo(x.ch), x.zn);
        x.ch/=x2, x.zn/=x2;
    }
}
main()
{
    //freopen("input.txt", "r", stdin);
    int n;
    cin>>n;
    int ar[n][2];
    dr xce={0, n}, yce={0, n};
    for(int a=0; a<n; a++)
    {
        cin>>ar[a][0]>>ar[a][1];
        ar[a][0]*=2, ar[a][1]*=2;
        xce.ch+=ar[a][0], yce.ch+=ar[a][1];
    }
    int q=0;
    if(n==1) q=1;
    for(int a=0; a<n; a++)
    {
        for(int b=0; b<n; b++)
        {
            if(a!=b)
            {
                int x=(ar[a][0]+ar[b][0])/2, y=(ar[a][1]+ar[b][1])/2;
                if(xce.ch==(x*xce.zn) and yce.ch==(y*yce.zn))
                {
                    q++;
                    break;
                }
            }
        }
    }
    if(q==n) cout<<-1;
    else
    {
        int an=0;
        set <dr> us;
        for(int a=0; a<n; a++)
        {
            int x=(ar[0][0]+ar[a][0])/2, y=(ar[0][1]+ar[a][1])/2;
            if(!(xce.ch==(x*xce.zn) and yce.ch==(y*yce.zn)))
            {
                dr vx={x*xce.zn-xce.ch, xce.zn}, vy={y*yce.zn-yce.ch, yce.zn};
                dr vec={vx.ch*vy.zn, vx.zn*vy.ch};
                norm(vec);
                    if(us.find(vec)==us.end())
                    {
                        us.insert(vec);
                        set <dr> pl, mi;
                        if(vec.ch!=0)
                        {
                            for(int b=0; b<n; b++)
                            {
                                dr vy2={(x-ar[b][0])*vec.zn, vec.ch};
                                dr y2={ar[b][1]*vy2.zn+vy2.ch, vy2.zn};
                                dr di={y*y2.zn-y2.ch, y2.zn};
                                norm(di);
                                if(di.ch>0) pl.insert(di);
                                if(di.ch<0)
                                {
                                    di.ch*=-1;
                                    mi.insert(di);
                                }
                            }
                        }
                        else
                        {
                            for(int b=0; b<n; b++)
                            {
                                dr di={x-ar[b][0], 1};
                                if(di.ch>0) pl.insert(di);
                                if(di.ch<0)
                                {
                                    di.ch*=-1;
                                    mi.insert(di);
                                }
                            }
                        }
                        if(pl.size()==mi.size())
                        {
                            set <dr>::iterator it=pl.begin(), it2=mi.begin();
                            bool ok=1;
                            while(it!=pl.end())
                            {
                                if((*it).ch!=(*it2).ch or (*it).zn!=(*it2).zn) ok=0;
                                it++, it2++;
                            }
                            an+=ok;
                        }
                    }

            }
        }
        cout<<an;
    }
}

#include <iostream>
#include <stack>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
#include <set>
#include <map>
#include <string>
#include <cstdio>
#include <unordered_map>
#include <iomanip>
#include <ctime>
#include <math.h>
#include <random>
using namespace std;

#define sqr(x) x * x
#define forn(n) for (int i = 0; i < n; ++i)
#define fornm(n, m) for (int i = 0; i < n; ++) for (int j = 0; j < m; ++j)
#define read(v) for (int i = 0; i < v.size(); ++i) cin >> v[i]
//#define output(v) for (int i = 0; i < v.size(); ++i) cout << v[i] << " ";
#define coutdouble fixed << setprecision(3)

typedef long long ll;
typedef unsigned int uint;
typedef vector<int> vint;
typedef vector<vector<int> > vvint;
typedef vector<long long> vll;
typedef vector<vector<long long> > vvll;
typedef pair<int, int> pint;
typedef pair<long long, long long> pll;

const long long MOD = 1e9 + 7;
const int MSIZE = 5e5;
const long long base = 7;
const double EPS = 1e-9;
const int INF = 1e9;

struct point{
    double x, y;
    point(): x(0), y(0){};
    point(double x, double y): 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);
    }
    point operator*(double d){
        return point(x * d, y * d);
    }
    point operator/(double d){
        return point(x / d, y / d);
    }
    bool operator==(point a){
        return abs(x - a.x) <= EPS && abs(y - a.y) <= EPS;
    }
    bool operator!=(point a){
        return abs(x - a.x) > EPS || abs(y - a.y) > EPS;
    }
    point normal(){
        point p(x, y);
        return p / sqrt(x * x + y * y);
    }
};

struct line{
    double a, b, c;
    line(): a(0), b(0), c(0) {};
    line(point _a, point _b){
        a = _a.y - _b.y;
        b = _b.x - _a.x;
        c = _a.x * _b.y - _a.y * _b.x;
    }
};

double dist(line l, point p){
    return (l.a * p.x + l.b * p.y + l.c) / sqrt(l.a * l.a + l.b * l.b);
}

point project(line l, point p){

    point a = point(-l.a, -l.b).normal();
    double d = dist(l, p);
    return p + a * d;
}

bool cmp(point a, point b){
    return abs(a.x - b.x) <= EPS ? a.y < b.y : a.x < b.x;
}

int main(){
    ios_base::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int n;
    cin >> n;
    vector<point> v(n);
    point mid;
    for (int i = 0; i < n; ++i){
        cin >> v[i].x >> v[i].y;
        mid.x += v[i].x, mid.y += v[i].y;
    }
    mid.x /= n, mid.y /= n;
    vector<char> used(n, 1);
    int cnt = 0;
    for (int i = 0; i < n; ++i){
        for (int j = i; j < n; ++j){
            if (!used[i] || !used[j])
                continue;
            if ((mid - v[i]) == (v[j] - mid)){
               used[i] = used[j] = 0;
               cnt++;
               if (i != j)
                   cnt++;
            }
        }
    }
    if (cnt == n){
        cout << -1;
        return 0;
    }
    int res = 0;
    int start = 0;
    for (int i = 0; i < n; ++i)
        if (!used[i]){
            start = i;
            break;
        }
    vector<line> out;
    for (int i = start; i < n; ++i){
        point tmid = (v[start] + v[i]) / 2;
        line l(mid, tmid);
        point p = project(l, point(0, 0));
        l = line(p, p + point(l.a, l.b));
        vector<point> tv;
        for (int j = 0; j < n; ++j)
            if (used[j])
                tv.push_back(project(l, v[j]));
        sort(tv.begin(), tv.end(), cmp);
        bool flag = 1;
        tmid = tv[0] + ((tv.back() - tv[0]) / 2);
        for (int j = 0; j < tv.size(); ++j)
            if (tmid - tv[j] != tv[int(tv.size()) - j - 1] - tmid)
                flag = 0;

        if (flag){
            out.push_back(l);
        }
    }
    vector<char> usedl(out.size(), 1);
    for (int i = 0; i < out.size(); ++i)
        for (int j = i + 1; j < out.size(); ++j)
            if (abs(dist(out[i], point(-out[j].b, out[j].a))) <= EPS)
                usedl[j] = 0;
    for (char a : usedl)
        res += a;
    cout << res;
#ifndef ONLINE_JUDGE
    cout << '\n' << coutdouble << double(clock()) / CLOCKS_PER_SEC;
#endif
    return 0;
}

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

const int N=1010;
int ti=150;
const double pi=acos(-1),eps=1e-6;
double block=pi/ti;
int n,T;
struct point
{
	double x,y;
}p[N];
inline point operator +(point a,point b){return (point){a.x+b.x,a.y+b.y};}
inline point operator -(point a,point b){return (point){a.x-b.x,a.y-b.y};}
inline point operator *(point a,double b){return (point){a.x*b,a.y*b};}
inline point operator /(point a,double b){return (point){a.x/b,a.y/b};}
inline point rotate(point a,double ang)
{
	return (point){a.x*cos(ang)-a.y*sin(ang),a.x*sin(ang)+a.y*cos(ang)};
}
inline double cross(point a,point b){return a.x*b.y-a.y*b.x;}
inline point across(point a,point b,point c,point d)
{
	double s1=cross(a-c,d-c),s2=cross(d-c,b-c);
	return a+(b-a)*s1/(s1+s2);
}
inline double len(point a){return sqrt(a.x*a.x+a.y*a.y);}
inline double dot(point a,point b){return a.x*b.x+a.y*b.y;}
double l[N];
inline int fcmp(double x){return x<-eps?-1:(x>eps?1:0);}

inline double f(double an)
{
	double ave=0.0;
	point tmp=rotate((point){10000000.0,0},an),line1=rotate((point){100.0,0},an),line2=rotate(line1,pi/2);
	//out(line1),out(line2);
	for(int i=1;i<=n;i++)
	{
		point P=p[i]+line2;
		point PP=across(P,p[i],(point){0,0},line1);
		l[i]=len(PP-tmp);//ave+=l[i];
	}
	for(int i=n;i>=1;i--)l[i]-=l[1],ave+=l[i];
	double re=0.0;
	sort(l+1,l+1+n);ave/=n;
	//for(int i=1;i<=n;i++)printf("%lf ",l[i]);puts("");
	for(int i=1;i<=n/2;i++)re+=fabs(fabs(l[i]-ave)-fabs(l[n-i+1]-ave));
	return re;
}
int ans;
inline void solve(int num)
{
	double L=num*block,R=(num+1)*block-eps;
	while(L+eps<=R)
	{
		double mid1=L+(R-L)/3,mid2=L+(R-L)/3*2;
		if(f(mid1)<f(mid2))
		{
			R=mid2;
		}else
		{
			L=mid1;
		}
	}
	//cout<<L<<' '<<f(L)<<endl;

	if(f(L)<eps)ans++;//cout<<L<<' '<<f(L)<<endl,ans++;
}
int main()
{
		scanf("%d",&n);ans=0;int inf=1;
		if(n<=200)ti=150,block=pi/ti;
		else ti=26,block=pi/ti;
		for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
		for(int i=1;i<=10;i++)
		{
			double tmp=(double)rand()/pow(2.0,31)*pi;
			if(f(tmp)>eps)
			{
				inf=0;
				break;
			}
		}
		if(inf)
		{
			puts("-1");
			return 0;
		}
		for(int i=0;i<ti;i++)
			solve(i);
		printf("%d\n",ans);//cout<<pi/4*3<<endl;
	return 0;
}

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

typedef double db;

const int N=2e3+5,M=N*N;
const db eps=1e-6;

struct P{
    db x,y;
    P(db _x=0,db _y=0) {x=_x;y=_y;}
    friend P operator + (P a,P b) {return P(a.x+b.x,a.y+b.y);}
    friend P operator - (P a,P b) {return P(a.x-b.x,a.y-b.y);}
    friend P operator * (P a,db x) {return P(a.x*x,a.y*x);}
}p[N],q[N],h;

int n,tot,ans;
bool vis[N];

struct node{
    P p;
    int a,b;
    db k;
}a[N*N];

bool cmp(node a,node b) {return a.k<b.k;}

db cross(P a,P b) {return a.x*b.y-a.y*b.x;}
db dot(P a,P b) {return a.x*b.x+a.y*b.y;}
db len(P a) {return sqrt(dot(a,a));}

int sgn(db x) {
    if (fabs(x)<eps) return 0;
    if (x>0) return 1;
    return -1;
}

bool check(node L,P p) {return fabs(dot(p-h,L.p))<eps;}

int main() {
       // freopen("life3.in","r",stdin);
       // freopen("life3.out","w",stdout);
        scanf("%d",&n);int nn=n;
        fo(i,1,n) {
            scanf("%lf%lf",&q[i].x,&q[i].y);
            h=h+q[i];
        }
        h=h*(1.0/n);
        fo(i,1,n-1)
                fo(j,i+1,n)
                        if (!sgn(cross(q[i]-h,q[j]-h))&&fabs(len(q[i]-h)-len(q[j]-h))<eps) {
                                vis[i]=vis[j]=1;
                                continue;
                        }
        int tmp=0;
        fo(i,1,n) if (!vis[i]) p[++tmp]=q[i];
        n=tmp;
        if (n<=2) {puts("-1");return 0;}
        fo(i,1,n-1)
                fo(j,i+1,n) {
                        db x=p[i].x+p[j].x-2*h.x;
                        db y=p[i].y+p[j].y-2*h.y;
                        a[++tot].p.x=y;a[tot].p.y=-x;
                        a[tot].a=i;a[tot].b=j;
                        if (a[tot].p.x<0) a[tot].p.x=-a[tot].p.x,a[tot].p.y=-a[tot].p.y;
                        if (fabs(a[tot].p.x)<eps) a[tot].p.y=fabs(a[tot].p.y);
                        if (fabs(a[tot].p.y)<eps) a[tot].p.x=fabs(a[tot].p.x);
                        a[tot].k=atan2(a[tot].p.y,a[tot].p.x);
                }
        sort(a+1,a+tot+1,cmp);
        if (nn==1000) {
                printf("%d\n",n);
                printf("%.8lf %.8lf\n",h.x,h.y);
        }
        for(int l=1,r=0;l<=tot;l=r+1) {
                while (r<tot&&!sgn(cross(a[r+1].p,a[l].p))) r++;
                if (r-l+1>=n/2) {
                        fo(i,1,n) vis[i]=0;
                        fo(i,l,r) if (!vis[a[i].a]&&!vis[a[i].b]) vis[a[i].a]=vis[a[i].b]=1;
                        int cnt=0,id=0;
                        fo(i,1,n)
                                if (!vis[i]) {
                                        cnt++;
                                        id=i;
                                }
                        if (cnt>0&&!(n&1)||cnt>1&&(n&1)) continue;
                        if (!cnt||check(a[l],p[id])) {
                                ans++;
                                if (nn==1000) printf("%.8lf %.8lf\n",a[l].p.x,a[l].p.y);
                        }
                }
        }
        printf("%d\n",ans);
        return 0;
}

#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++){
        checks.push_back(z[0] + z[i]);
    }
    /*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);
            }
        }
    }

    if(test50){
        cout << checks.size() << endl;
    }*/

    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 fr(a, b, c) for(int a = b; a < (int) c; ++a)
using namespace std;
typedef pair<int, int> ii;

const long double INF = 1e100;
const long double EPS = 1e-10;
const long double PI = acos(-1.0);

int cmp(long double a, long double b = 0.0) {
  if (fabs(a-b) < EPS) return 0;
  else if (a < b) return -1;
  return 1;
}

struct PT {
  long double x,y;
  PT() {}
  PT(long double x, long double y) : x(x), y(y){}
  PT(const PT &p) : x(p.x), y(p.y){}
  PT operator +(const PT &p)     const { return PT(x+p.x,y+p.y); }
  PT operator -(const PT &p)     const { return PT(x-p.x,y-p.y); }
  PT operator *(long double c)        const { return PT(x*c,y*c);     }
  PT operator /(long double c)        const { return PT(x/c,y/c);     }
  long double operator *(const PT &p) const { return x*p.x+y*p.y;     }
  long double operator %(const PT &p) const { return x*p.y-y*p.x;     }
  long double operator !()            const { return sqrt(x*x+y*y);   }
  long double operator ^(const PT &p) const { return (atan2(*this%p,*this*p)); }
  bool operator ==(const PT &p)  const { return cmp(x,p.x)==0 && cmp(y,p.y)==0; }
  bool operator <(const PT &p)   const {
    if (cmp(x,p.x)!=0) return cmp(x,p.x)==-1;
    return cmp(y,p.y)==-1;
  }
};

ostream &operator<<(ostream &os, const PT &p) {
  os << "(" << p.x << "," << p.y << ")";
}

// roda o ponto CCW ou CW ao redor da origem
PT rotateCCW90(PT p) { return PT(-p.y,p.x); }
PT rotateCW90(PT p)  { return PT(p.y,-p.x); }
PT rotateCCW(PT p, long double t) {
  return PT(p.x * cos(t) - p.y * sin(t), p.x * sin(t) + p.y * cos(t));
}

// projeta ponto c na linha através de a e b
// assume a != b
PT projPtLine(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  return a + b * (c*b) / (b*b);
}

// projeta ponto c no segmento através de a e b
PT projPtSeg(PT a, PT b, PT c) {
  b = b - a; c = c - a;
  long double r = b * b;
  if (cmp(r) == 0) return a;
  r = c * b / r;
  if (r < 0) return a;
  if (r > 1) return a+b;
  return a + b * r;
}

bool azul[12345];

int main() {
    srand(time(NULL));
    ios::sync_with_stdio(0);
    int n;
    cin >> n;
    vector<PT> pts;
    PT cent(0,0);
    fr(i, 0, n) {
        int a, b;
        cin >> a >> b;
        pts.push_back(PT(a, b));
        cent = cent + PT(a, b);
    }
    cent = cent / n;
    vector<PT> r_pts;
    fr(i, 0, n) {
        if(pts[i] == cent) {
            azul[i] = true;
        }
        fr(j, i + 1, n) {
            if(!azul[i] && !azul[j] && (pts[i] + pts[j]) / 2 == cent) {
                azul[i] = azul[j] = true;
            }
        }
    }
    fr(i, 0, n) {
        if(!azul[i]) {
            r_pts.push_back(pts[i]);
        }
    }
    pts = r_pts;
    n = pts.size();
    if(n == 0) {
        cout << -1 << endl;
        return 0;
    }

    int ans = 1e9;

    fr(kk, 0, min(3, n)) {
        vector<long double> angles;
        int res = 0;
        int bicho = rand() % n;
        PT a = pts[bicho];
        fr(i, 0, n) {
            PT b = pts[i];
            PT media = (a + b) / 2;
            PT vec = (media - cent);
            PT perp = rotateCCW90(vec);

            long double angle = PT(1, 0) ^ perp;
            if(cmp(angle) < 0) angle += PI;
            bool continua = false;
            for(auto a : angles) {
                if(cmp(angle, a) == 0) {
                    continua = true;
                    break;
                }
            }
            angles.push_back(angle);
            if(continua) continue;

            vector<long double> dists;
            fr(i, 0, n) {
                PT proj = projPtLine(cent, cent + perp, pts[i]);

                int sign = proj < cent ? 1 : -1;

                if (cmp(!(proj - cent)) == 0) continue;
                dists.push_back(!(proj - cent) * sign);
            }
            sort(dists.begin(), dists.end());

            bool ok = true;
            fr(i, 0, dists.size()) {
                if(cmp(dists[i] + dists[dists.size() - i - 1]) != 0) {
                    ok = false;
                    break;
                }
            }
            if(ok) ++res;
        }
        ans = min(ans, res);
    }

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

#include <bits/stdc++.h>
#include <ext/pb_ds/priority_queue.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define pd __gnu_pbds
#define st first
#define nd second
#define all(x) (x).begin(), (x).end()

using namespace std;
using namespace placeholders;

using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
template <class T> using il = initializer_list<T>;

template <class T> inline void mini(T &l, T r){l = min(l, r);}
template <class T> inline void maxi(T &l, T r){l = max(l, r);}

template <class T> void _dbg(const char *sdbg, T &&h){cerr << sdbg << "=" << h << "\n";}
template <class T, class ...R> void _dbg(const char *sdbg, T h, R... a){
	while (*sdbg != ','){cerr << *sdbg++;} cerr << "=" << h << ","; _dbg(sdbg + 1, a...);}
template <class L, class R> ostream &operator <<(ostream &os, const pair<L, R> &P){
	return os << "(" << P.st << "," << P.nd << ")";}
template <class T> ostream &operator <<(ostream &os, const vector<T> &v){
	os << "["; for (auto x: v) os << x << ","; return os << "]";}
template <class IT, class V = vector<typename iterator_traits<IT>::value_type>> V gr(IT b, IT e){
	return V(b, e);}
template <class T, class c = decltype(T().begin()), typename enable_if<!is_same<T, string>::value>::type* = nullptr> ostream &operator <<(ostream &os, T &v){
	return os << gr(v.begin(), v.end());}
template <class T, int I, int N, typename enable_if<I == N, T>::type* = nullptr> void TuplePrint(ostream &os, T val){
	os << get<N>(val);}
template <class T, int I, int N, typename enable_if<I < N, T>::type* = nullptr> void TuplePrint(ostream &os, T val){
	os << get<I>(val) << ","; TuplePrint<T, I + 1, N>(os, val);}
template <class... Ts> ostream &operator<<(ostream &os, tuple<Ts...> t){
	os << "("; TuplePrint<tuple<Ts...>, 0, sizeof...(Ts) - 1>(os, t); return os << ")";}

#ifdef SFIC
#define eput(...) do{cerr << __LINE__;_dbg("\t| "#__VA_ARGS__, __VA_ARGS__);}while(0)
#else
#define eput(...) 218
#endif

//pd::priority_queue<int, less<int>, pairing_heap_tag>
//pd::tree<int, int, less<int>, pd::rb_tree_tag, pd::tree_order_statistics_node_update>
//constexpr int N = 1E5 + 10, M = 1E9 + 7;
//constexpr ll INF = LLONG_MAX >> 1;
//constexpr double eps = 1E-9;

const int N = 2E3 + 10;

int n;
ll x[N], y[N];
ll sx, sy;

bool sym(const multiset<ll> &a){
    multiset<ll> b;
    for (auto &x: a)
        b.emplace(-x);
    return a == b;
}

bool checkc(ll cx, ll cy){
    multiset<ll> lst;
    eput(cx, cy);
    for (int i = 0; i < n; ++i)
        lst.emplace(cx * x[i] + cy * y[i]);
    eput(lst);
    return sym(lst);
}

ll gcd(ll a, ll b){
    ll t;
    while (b != 0){
        t = a % b;
        a = b;
        b = t;
    }
    return a;
}

int main(){
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
        scanf("%lld%lld", x + i, y + i);
    ll sx = accumulate(x, x + n, 0ll);
    ll sy = accumulate(y, y + n, 0ll);
    for (int i = 0; i < n; ++i)
        x[i] = n * x[i] - sx, y[i] = n * y[i] - sy;

    for (int i = 0; i < n; ++i){
        if (x[0] == 0 && y[0] == 0){
            --n;
            x[i] = x[n], y[i] = x[n];
            --i;
            continue;
        }

        int j = i + 1;
        for (; j < n && !(x[i] == -x[j] && y[i] == -y[j]); ++j);
        if (j < n){
            --n;
            x[j] = x[n], y[j] = x[n];
            --n;
            x[i] = x[n], y[i] = x[n];
            --i;
        }
    }

    if (n == 0){
        puts("-1");
        return 0;
    }

    eput(gr(x, x + n));
    eput(gr(y, y + n));

    set<pll> lst;
    x[n] = y[n] = 0;
    for (int i = 1; i <= n; ++i){
        ll a = -(y[0] + y[i]), b = x[0] + x[i];
        ll d = gcd(a, b);
        a /= d, b /= d;

        if (a < 0)
            a = -a, b = -b;
        if (checkc(a, b))
            lst.emplace(a, b);
    }
    printf("%d\n", lst.size());
    return 0;
}

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <iomanip>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cstdint>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
#define MP make_pair
#define PB push_back
#define inf 1000000007
#define rep(i,n) for(int i = 0; i < (int)(n); ++i)
#define all(x) (x).begin(),(x).end()

template<typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val){
    std::fill( (T*)array, (T*)(array+N), val );
}

template<class T> inline bool chmax(T &a, T b){
    if(a<b){
        a = b;
        return true;
    }
    return false;
}

template<class T> inline bool chmin(T &a, T b){
    if(a>b){
        a = b;
        return true;
    }
    return false;
}
// template<typename T> class Rational {
// private:
//     static Rational make(const T& x, const T& y){
//         Rational m; return m.num = x, m.den = y, m;
//     }
// public:
//     friend ostream& operator<<(ostream& os, const Rational& rn) {
//         return (os << rn.num << " / " << rn.den);
//     }
//     Rational& operator=(T val){ return *this = Rational(val); }
//     bool operator<(const Rational& val) const { return num*val.den < den*val.num; }
//     bool operator<(const T val) const { return *this < Rational(val); }
//     friend bool operator<(const T val1, const Rational& val2){ return Rational(val1) < val2; }
//     bool operator>(const Rational& val) const { return val < *this; }
//     bool operator>(const T val) const { return *this > Rational(val); }
//     friend bool operator>(const T val1, const Rational& val2){ return Rational(val1) > val2; }
//     bool operator<=(const Rational& val) const { return !(*this > val); }
//     bool operator<=(const T val) const { return *this <= Rational(val); }
//     friend bool operator<=(const T val1, const Rational& val2){ return Rational(val1) <= val2; }
//     bool operator>=(const Rational& val) const { return !(*this < val); }
//     bool operator>=(const T val) const { return *this >= Rational(val); }
//     friend bool operator>=(const T val1, const Rational& val2){ return Rational(val1) >= val2; }
//     bool operator==(const Rational& val) const { return num*val.den == den*val.num; }
//     bool operator==(const T val) const { return *this == Rational(val); }
//     friend bool operator==(const T val1, const Rational& val2){ return Rational(val1) == val2; }
//     bool operator!=(const Rational& val) const { return !(*this == val); }
//     bool operator!=(const T val) const { return *this != Rational(val); }
//     friend bool operator!=(const T val1, const Rational& val2){ return Rational(val1) != val2; }
//     explicit operator bool() const noexcept { return num; }
//     bool operator!() const noexcept { return !static_cast<bool>(*this); }
//     Rational operator+() const { return *this; }
//     Rational operator-() const { return make(-num, den); }
//     friend Rational abs(const Rational& val){ return make(abs(val.num), val.den); }
//     Rational operator+(const Rational& val) const { return make(num*val.den+val.num*den, den*val.den); }
//     Rational operator+(T val) const { return *this + Rational(val); }
//     friend Rational operator+(T a, const Rational& b){ return b + a; }
//     Rational& operator+=(const Rational& val){ return *this = *this + val; }
//     Rational& operator+=(const T& val){ return *this = *this + val; }
//     Rational& operator++(){ return *this += 1; }
//     Rational operator++(int){ return make(num + den, den); }
//     Rational operator-(const Rational& val) const { return make(num*val.den-val.num*den, den*val.den); }
//     Rational operator-(T val) const { return *this - Rational(val); }
//     friend Rational operator-(T a, const Rational& b){ return Rational(a) - b; }
//     Rational& operator-=(const Rational& val){ return *this = *this - val; }
//     Rational& operator-=(const T& val){ return *this = *this - val; }
//     Rational& operator--(){ return *this -= 1; }
//     Rational operator--(int){ return make(num - den, den); }
//     Rational operator*(const Rational& val) const { return make(num*val.num, den*val.den); }
//     Rational operator*(T val) const { return *this * Rational(val); }
//     friend Rational operator*(T a, const Rational& b){ return b * a; }
//     Rational& operator*=(const Rational& val){ return *this = *this * val;}
//     Rational& operator*=(const T& val){ return *this = *this * val; }
//     Rational operator/(const Rational& val) const { return make(num*val.den, den*val.num); }
//     Rational operator/(T val) const { return *this / Rational(val); }
//     friend Rational operator/(T a, const Rational& b){ return Rational(a) / b; }
//     Rational& operator/=(const Rational& val){ return *this / val; }
//     Rational& operator/=(const T& val){ return *this = *this / val; }

//     T num, den;

//     Rational(){}
//     Rational(T num_) : num(num_), den(1){}
//     Rational(T num_, T den_) : num(num_), den(den_){ if(den < 0) num = -num, den = -den; }
// };
// using R = Rational<ll>;
#define EPS 1e-10
struct point{
    long double x;
    long double y;
    point(){};
};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n;
    cin >> n;
    vector<ll>x(n),y(n);
    // vector<pair<R,R> >p;
    vector<point> v;
    long double sx = 0.0,sy = 0.0;
    rep(i,n){
        cin >> x[i] >> y[i];
        sx += x[i];
        sy += y[i];
    }
    if(n<=2){
        cout << -1 << endl;
        return 0;
    }
    sx /= (long double)n;
    sy /= (long double)n;
    rep(i,n){
        if(abs(sx-x[i])<=EPS&&abs(sy-y[i])<=EPS){

        }else{
            // p.push_back(MP(R(x[i]),R(y[i])));
            point a;
            a.x = x[i];
            a.y = y[i];
            v.push_back(a);
        }
    }
    n = v.size();

    if(n<=2){
        cout << -1 << endl;
        return 0;
    }
    bool ok = 1;
    vector<pair<long double,long double> > s;
    rep(i,n){
        s.push_back(MP(v[0].x,v[0].y));
    }
    sort(s.begin(),s.end());
    rep(i,n){
        if(abs(s[i].first+s[n-1-i].first - 2*sx)>EPS||abs(s[i].second+s[n-1-i].second - 2*sy)>EPS){
            ok = 0;
        }
    }
    if(ok){
        cout << -1 << endl;
        return 0;
    }
    vector<pair<long double,long double> > res;
    if(n%2==0){
        rep(i,n-1){
            point a = v[0];
            point b = v[i+1];
            long double mx = (a.x+b.x)/2.0;
            long double my = (a.y+b.y)/2.0;
            long double rx = (mx-sx);
            long double ry = (my-sy);
            swap(rx,ry);
            ry = -ry;
            long double d = sqrt(rx*rx+ry*ry);

            rx /= d;
            ry /= d;
            if(rx<0){
                rx = -rx;
                ry = -ry;
            }
            vector<long double> s;
            rep(j,n){
                long double X = v[j].x;
                long double Y = v[j].y;
                s.push_back(rx * (sx-X) + ry*(sy-Y));
            }
            sort(s.begin(),s.end());
            bool ng = 0;
            rep(j,n){
                if(abs(s[j]+s[n-1-j])>EPS){
                    ng = 1;
                }
            }
            if(!ng){
                res.push_back(MP(rx,ry));
            }
        }
    }else{
        rep(i,n){
            point a = v[i];
            long double mx = a.x;
            long double my = a.y;
            long double rx = (mx-sx);
            long double ry = (my-sy);
            swap(rx,ry);
            ry = -ry;
            long double d = sqrt(rx*rx+ry*ry);
            rx /= d;
            ry /= d;
            if(rx<0){
                rx = -rx;
                ry = -ry;
            }
            vector<long double> s;
            rep(j,n){
                long double X = v[j].x;
                long double Y = v[j].y;
                s.push_back(rx * (sx-X) + ry*(sy-Y));
            }
            sort(s.begin(),s.end());
            bool ng = 0;
            rep(j,n){
                if(abs(s[j]+s[n-1-j])>EPS){
                    ng = 1;
                }
            }
            if(!ng){
                res.push_back(MP(rx,ry));
            }
        }
    }
    sort(res.begin(),res.end());
    int m = res.size();
    int sm = m;
    rep(i,m-1){
        if(abs(res[i].first-res[i+1].first)<=EPS&&abs(res[i].second-res[i+1].second)<=EPS){
            sm--;
        }
    }
    cout << sm << endl;
    return 0;
}

#include<bits/stdc++.h>
#define N 2010
#define ll long long
#define db long double
#define pp pair<int,int>
#define fi first
#define se second
#define int long long
using namespace std;
const db eps=1e-8;
int T,n;
int x[N],y[N];
multiset<pp>Set;
multiset<pp>::iterator it;
db s[N*N],tmp[N];
int tot;
int ans;
db a,b;
void work(db k){
	for(int i=1;i<=n;i++)tmp[i]=(y[i]-b/2.0)*k+x[i]-a/2.0;
	sort(tmp+1,tmp+n+1);
	for(int i=1;i<=(n+1)/2;i++)if(fabs(tmp[i]+tmp[n-i+1])>eps)return;
	ans++;
//	cout<<"!!"<<k<<endl;
}
void work2(){
	for(int i=1;i<=n;i++)tmp[i]=y[i];
	sort(tmp+1,tmp+n+1);
	db gg=(tmp[1]+tmp[n])/2.0;
	for(int i=1;i<=(n+1)/2;i++)if(fabs((tmp[i]+tmp[n-i+1])/2.0-gg)>eps)return;
	ans++;
}
signed main(){
//	freopen("life.in","r",stdin);
//	freopen("life.out","w",stdout);
	scanf("%lld",&n);
	ll sumx=0,sumy=0;
	tot=0;
	ans=0;
	for(int i=1;i<=n;i++){
		scanf("%lld%lld",&x[i],&y[i]);
		sumx+=x[i],sumy+=y[i];
	}

	a=sumx*2.0/n,b=sumy*2.0/n;
//	cout<<a<<" "<<b<<endl;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if(fabs(y[i]+y[j]-b)<eps)continue;
			s[++tot]=-(x[i]+x[j]-a)*1.0/(y[i]+y[j]-b);
//			cout<<i<<" "<<j<<" "<<s[tot]<<endl;
		}
	}
	sort(s+1,s+tot+1);

	if((sumx*2)%n==0&&(sumy*2)%n==0){
		Set.clear();
		ll g1=sumx*2/n,g2=sumy*2/n;
		for(int i=1;i<=n;i++){
			it=Set.lower_bound(pp(g1-x[i],g2-y[i]));
			if(it!=Set.end()&&(*it).fi==g1-x[i]&&(*it).se==g2-y[i])Set.erase(it);
			else Set.insert(pp(x[i],y[i]));
		}
		if(n%2==1&&g1%2==0&&g2%2==0){
			it=Set.lower_bound(pp(g1/2,g2/2));
			if(it!=Set.end()&&(*it).fi==g1/2&&(*it).se==g2/2)Set.erase(it);
		}
//		n=0;
//		for(it=Set.begin();it!=Set.end();it++){
//			x[++n]=(*it).fi,y[n]=(*it).se;
//		}
//		cout<<n<<" "<<g1<<" "<<g2<<endl;
		if(Set.begin()==Set.end()){
			printf("-1\n");
			return 0;
		}
	}
//	cout<<n<<endl;
//	for(int i=1;i<=n;i++)cout<<x[i]<<" "<<y[i]<<endl;
	work2();

	int num=1;
	for(int i=2;i<=tot;i++){
		if(fabs(s[i]-s[i-1])<eps)num++;
		else {
//			cout<<i-1<<" "<<s[i-1]<<" "<<num<<endl;
			if(num>=n/2)work(s[i-1]);
			num=1;
		}
	}
//	cout<<n<<" "<<s[n]<<" "<<num<<endl;
	if(num>=n/2)work(s[tot]);
	printf("%lld\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];

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;
    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 ++;
    }

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

    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);
        /*
        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 <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <string>
#include <stack>
#include <set>
#include <cassert>
#include <ctime>
#include <unordered_set>
#include <complex>
#include <queue>

#define vd vector<double>
#define pb push_back
#define all(v) v.begin(), v.end()
#define x first
#define y second
#define mp make_pair
#define forn(i, l) for (int i = 0; i < l; i++)

using namespace std;
typedef pair<int, int> pi;
typedef pair<double, double> pd;
typedef long long li;
const int N = 2e3 + 10;
const double eps = 0.0000001, eps2 = 0.0001;
const int INF = (int)1e9 + 2;
const long long LINF = 1e16;
const double PI = acos(-1.0);

int n;
pi mas[N];
pd temp[N];
char used[N];
double cx, cy;

int main() {
#ifdef _DEBUG
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	scanf("%d", &n);
	forn(i, n) {
		scanf("%d%d", &mas[i].x, &mas[i].y);
		cx += mas[i].x;
		cy += mas[i].y;
	}
	cx /= n;
	cy /= n;
	int r = n;
	forn(i, n) {
		if (used[i]) {
			continue;
		}
		if (abs(mas[i].x - cx) < eps && abs(mas[i].y - cy) < eps) {
			used[i] = 1;
			mas[i].x = mas[i].y = INF;
			r--;
			continue;
		}
		forn(j, i) {
			if (abs(cx * 2 - mas[i].x - mas[j].x) < eps && abs(cy * 2 - mas[i].y - mas[j].y) < eps) {
				used[i] = used[j] = 1;
				mas[i].x = mas[i].y = INF;
				mas[j].x = mas[j].y = INF;
				r -= 2;
				break;
			}
		}
	}
	sort(mas, mas + n);
	if (r < 1) {
		printf("-1");
		return 0;
	}
	vector<pd> ans;
	int sz = 0;
	forn(i, r) {
		double x2 = (mas[0].x + mas[i].x) * 0.5;
		double y2 = (mas[0].y + mas[i].y) * 0.5;
		double a = cx - x2, b = cy - y2;
		double c = a * x2 + b * y2;
		double l = (b * b + a * a);
		forn(j, r) {
			double del = (c - a * mas[j].x - b * mas[j].y) / l;
			temp[j].x = mas[j].x + del * a, temp[j].y = mas[j].y + del * b;
		}
		sort(temp, temp + r);
		bool ok = 1;
		forn(j, (r + 1) / 2) {
			if (abs(2 * x2 - temp[j].x - temp[r - 1 - j].x) >= eps || abs(2 * y2 - temp[j].y - temp[r - 1 - j].y) >= eps) {
				ok = 0;
				break;
			}
		}
		if (ok) {
			ans.pb(mp(a / sqrt(l), b / sqrt(l)));
		}
	}
	sort(all(ans));
	forn(i, ((int)ans.size()) - 1) {
		if (abs(ans[i].x - ans[i + 1].x) < eps && abs(ans[i].y - ans[i + 1].y) < eps) {
			sz++;
		}
	}
	printf("%d", ans.size() - sz);
	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-6
//#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>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;

#define FOR(i, a, b) for (int i=a; i<(b); i++)
#define F0R(i, a) for (int i=0; i<(a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)

#define sz(x) (int)(x).size()
#define mp make_pair
#define pb emplace_back
#define A first
#define B second
#define lb lower_bound
#define ub upper_bound
int mat[2000][2000]; //0 if always, 1 if never, 2 if once
int main(){
	int N; cin >> N;
	vector<pii> vpts;
	long long xcm = 0;
	long long ycm = 0;
	for (int i = 0; i < N; i++){
		int x, y; cin >> x >> y;
		vpts.push_back(pii(x, y));
		xcm += x;
		ycm += y;
	}
	//X + rY is the formula we're using
	for (int i = 0; i < N; i++){
		for (int j = 0; j < N; j++){
			long long x1 = vpts[i].first + vpts[j].first;
			long long y1 = vpts[j].second + vpts[i].second;
			if (y1*N == ycm*2LL){
				if (x1*N == xcm*2LL){
					mat[i][j] = 2;
				}
				else{
					mat[i][j] = 0;
				}
			}
			else{
				mat[i][j] = 1;
			}
		}
	}
	int minoverallm = 3;
	for (int i = 0; i < N; i++){
		int minele = 3;
		int maxele = -1;
		for (int j = 0; j < N; j++){
			minele = min(minele, mat[i][j]);
			maxele = max(maxele, mat[i][j]);
		}
		if (maxele == 0){
			cout << 0 << endl;
			return 0;
		}
		minoverallm = min(minoverallm, maxele);
	}
	if (minoverallm == 2){
		cout << -1 << endl;
		return 0;
	}
	int res = 0;
	for (int i = 0; i < N; i++){
		int minele = 3;
		int maxele = -1;
		for (int j = 0; j < N; j++){
			minele = min(minele, mat[i][j]);
			maxele = max(maxele, mat[i][j]);
		}
		if (maxele == 1){
			//do it.
			for (int j = 0; j < N; j++){
				if (mat[i][j] == 1){
					long long firstcoeff = (vpts[i].first + vpts[j].first)*N;
					long long secondcoeff = (vpts[i].second + vpts[j].second)*N;
					long long thirdcoeff = xcm*2;
					long long fourthcoeff = ycm*2;
					long long fifthcoeff = firstcoeff - thirdcoeff;
					long long sixthcoeff = fourthcoeff - secondcoeff;
					vector<long long> all;
					long double d1 = 0;
					for (int k = 0; k < N; k++){
						all.push_back(sixthcoeff * vpts[k].first + fifthcoeff * vpts[k].second);
						d1 += sixthcoeff * vpts[k].first + fifthcoeff * vpts[k].second;
					}
					sort(all.begin(), all.end());
					d1 /= ((long double) N);
					bool works = true;
					for (int k = 0; k < N; k++){
						if (abs(all[i] + all[N - i - 1] - 2*d1) > 1e-8){
							works = false;
							break;
						}
					}
					if (works){
						res++;
					}
				}
			}
			break;
		}
	}
	vector<long long> ys;
	bool works = true;
	for (int i = 0; i < N; i++){
		ys.push_back(vpts[i].first);
	}
	long double mean = 0.0;
	for (int i = 0; i < N; i++){
		mean += ys[i];
	}
	mean /= ((long double) N);
	for (int i = 0; i < N; i++){
		if (abs(ys[i] + ys[N - i - 1] - 2*mean) > 1e-8){
			works = false;
			break;
		}
	}
	if (works){
		res++;
	}
	cout << res << endl;

}