Problem Statement

Fox Ciel is practicing miniature golf, a golf game played with a putter club only. For improving golf skills, she believes it is important how well she bounces the ball against walls.

The field of miniature golf is in a two-dimensional plane and surrounded by $N$ walls forming a convex polygon. At first, the ball is placed at $(s_x, s_y)$ inside the field. The ball is small enough to be regarded as a point.

Ciel can shoot the ball to any direction and stop the ball whenever she wants. The ball will move in a straight line. When the ball hits the wall, it rebounds like mirror reflection (i.e. incidence angle equals reflection angle).

For practice, Ciel decided to make a single shot under the following conditions:

* The ball hits each wall of the field exactly once.

* The ball does NOT hit the corner of the field.




Count the number of possible orders in which the ball hits the walls.

Input

The input contains several datasets. The number of datasets does not exceed $100$. Each dataset is in the following format.

> $N$
> $s_x$ $s_y$
> $x_1$ $y_1$
> :
> :
> $x_N$ $y_N$

The first line contains an integer $N$ ($3 \leq N \leq 8$). The next line contains two integers $s_x$ and $s_y$ ($-50 \leq s_x, s_y \leq 50$), which describe the coordinates of the initial position of the ball. Each of the following $N$ lines contains two integers $x_i$ and $y_i$ ($-50 \leq x_i, y_i \leq 50$), which describe the coordinates of each corner of the field. The corners are given in counterclockwise order. You may assume given initial position $(s_x, s_y)$ is inside the field and the field is convex.

It is guaranteed that there exists a shoot direction for each valid order of the walls that satisfies the following condition: distance between the ball and the corners of the field $(x_i, y_i)$ is always greater than $10^{-6}$ until the ball hits the last wall.

The last dataset is followed by a line containing a single zero.

Output

For each dataset in the input, print the number of valid orders of the walls in a line.

Sample Input


4
0 0
-10 -10
10 -10
10 10
-10 10
0

Output for the Sample Input


8





Example

Input

4
0 0
-10 -10
10 -10
10 10
-10 10
0


Output

8
#include <set>
#include <cmath>
#include <cstdio>
#include <vector>
#include <cassert>
#include <algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

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

struct point{
	double x,y;
	point():x(0),y(0){}
	point(double x,double y):x(x),y(y){}
	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); }
	bool operator==(const point &a)const{ return abs(x-a.x)<EPS && abs(y-a.y)<EPS; }
	bool operator!=(const point &a)const{ return abs(x-a.x)>EPS || abs(y-a.y)>EPS; }
};

point operator*(double c,const point &a){ return point(c*a.x,c*a.y); }

inline double dot(const point &a,const point &b){ return a.x*b.x+a.y*b.y; }

inline double cross(const point &a,const point &b){ return a.x*b.y-a.y*b.x; }

inline point rot(const point &a,double theta){ return point(a.x*cos(theta)-a.y*sin(theta),a.x*sin(theta)+a.y*cos(theta)); }

inline double arg(const point &a){ double t=atan2(a.y,a.x); return t<0?t+2*PI:t; }

struct segment{
	point a,b;
	segment(){}
	segment(const point &a,const point &b):a(a),b(b){}
};

typedef vector<point> polygon;

enum{CCW=1,CW=-1,ON=0};
inline int ccw(const point &a,const point &b,const point &c){
	double rdir=cross(b-a,c-a);
	if(rdir> EPS) return CCW;
	if(rdir<-EPS) return CW;
	return ON;
}

inline bool intersect(const segment &S1,const segment &S2){
	if(max(S1.a.x,S1.b.x)+EPS<min(S2.a.x,S2.b.x)
	|| max(S1.a.y,S1.b.y)+EPS<min(S2.a.y,S2.b.y)
	|| max(S2.a.x,S2.b.x)+EPS<min(S1.a.x,S1.b.x)
	|| max(S2.a.y,S2.b.y)+EPS<min(S1.a.y,S1.b.y)) return false;
	return ccw(S1.a,S1.b,S2.a)*ccw(S1.a,S1.b,S2.b)<=0
		&& ccw(S2.a,S2.b,S1.a)*ccw(S2.a,S2.b,S1.b)<=0;
}

inline bool cover(const segment &S,const point &p){
	return abs(cross(S.a-p,S.b-p))<EPS && dot(S.a-p,S.b-p)<EPS;
}

inline point get_intersect(const segment &S1,const segment &S2){
	double a1=cross(S1.b-S1.a,S2.b-S2.a);
	double a2=cross(S1.b-S1.a,S1.b-S2.a);
	if(abs(a1)<EPS){
		if(cover(S1,S2.a)) return S2.a;
		if(cover(S1,S2.b)) return S2.b;
		if(cover(S2,S1.a)) return S1.a;
		return S1.b;
	}
	return S2.a+a2/a1*(S2.b-S2.a);
}

bool is_perm(vector<int> a){
	sort(a.begin(),a.end());
	return unique(a.begin(),a.end())-a.begin()==a.size();
}

vector<int> simulate(point p,const polygon &F,double theta){
	int n=F.size();
	vector<int> res;
	bool used[8]={};
	while(res.size()<n){
		point v(cos(theta),sin(theta));
		segment S(p,p+200*v);

		int i0=-1;
		segment e; // 反射する辺
		point q; // 反射する点
		rep(i,n){
			e=segment(F[i],F[(i+1)%n]);
			if(intersect(S,e)){
				q=get_intersect(S,e);
				if(q!=p){
					i0=i;
					break;
				}
			}
		}

		assert(i0!=-1);
		if(used[i0]) return res; // 同じ辺に二回反射したらダメ
		used[i0]=true;

		if(q==e.a || q==e.b) return res; // 角に当たったらダメ

		res.push_back(i0);

		// 反射角を求める
		double phi=arg(e.b-e.a);
		point dir=rot(q-p,-phi);
		dir.y*=-1;
		dir=rot(dir,phi);
		theta=arg(dir);

		p=q;
	}

	return res;
}

void dfs(point s,int cnt,int used,polygon G,vector<double> &theta){
	int n=G.size();

	if(cnt==n-1){
		int i;
		for(i=0;used&(1<<i);i++);
		theta.push_back(arg(G[i]-s));
		theta.push_back(arg(G[(i+1)%n]-s));
		return;
	}

	rep(i,n) if(!(used&(1<<i))) {
		theta.push_back(arg(G[i]-s));
		theta.push_back(arg(G[(i+1)%n]-s));

		segment e(G[i],G[(i+1)%n]);
		polygon H(n);
		rep(j,n){
			point p=G[j];
			// p を e に対称な位置に移す
			double phi=arg(e.b-e.a);
			point tmp=rot(p-e.a,-phi);
			tmp.y*=-1;
			H[j]=rot(tmp,phi)+e.a;
		}
		dfs(s,cnt+1,used|(1<<i),H,theta);
	}
}

bool eq(double a,double b){ return abs(a-b)<EPS; }

int main(){
	for(int n;scanf("%d",&n),n;){
		point s; scanf("%lf%lf",&s.x,&s.y);
		polygon F(n);
		rep(i,n) scanf("%lf%lf",&F[i].x,&F[i].y);

		vector<double> theta;
		dfs(s,0,0,F,theta);
		sort(theta.begin(),theta.end());
		theta.erase(unique(theta.begin(),theta.end(),eq),theta.end());
		theta.push_back(theta[0]+2*PI);

		vector<double> phi;
		rep(i,(int)theta.size()-1) phi.push_back((theta[i]+theta[i+1])/2);

		set< vector<int> > ans;
		// TLE が厳しいので 1 つ置きにシミュレーション. 2 つが同じ結果ならスキップしたものも同じ結果
		vector<int> prev;
		static bool skip[200000];
		rep(i,phi.size()) skip[i]=false;
		rep(i,phi.size()/2){
			vector<int> hit=simulate(s,F,phi[2*i]);
			if(hit.size()==n && is_perm(hit)){
				ans.insert(hit);
				if(hit==prev) skip[2*i-1]=true;
			}
			prev=hit;
		}
		rep(i,phi.size()/2+1){
			if(2*i+1<phi.size() && !skip[2*i+1]){
				vector<int> hit=simulate(s,F,phi[2*i+1]);
				if(hit.size()==n && is_perm(hit)){
					ans.insert(hit);
				}
			}
		}

		printf("%d\n",ans.size());
	}

	return 0;
}