Problem:
Score : 700 points

Problem Statement

You are given N points (x_i,y_i) located on a two-dimensional plane.
Consider a subset S of the N points that forms a convex polygon.
Here, we say a set of points S forms a convex polygon when there exists a convex polygon with a positive area that has the same set of vertices as S. All the interior angles of the polygon must be strictly less than 180°.

For example, in the figure above, {A,C,E} and {B,D,E} form convex polygons; {A,C,D,E}, {A,B,C,E}, {A,B,C}, {D,E} and {} do not.

For a given set S, let n be the number of the points among the N points that are inside the convex hull of S (including the boundary and vertices). Then, we will define the score of S as 2^{n-|S|}.

Compute the scores of all possible sets S that form convex polygons, and find the sum of all those scores.

However, since the sum can be extremely large, print the sum modulo 998244353.

Constraints

1≤N≤200

0≤x_i,y_i<10^4 (1≤i≤N)

If i≠j, x_i≠x_j or y_i≠y_j.

x_i and y_i are integers.

Input

The input is given from Standard Input in the following format:

N
x_1 y_1
x_2 y_2
:
x_N y_N

Output

Print the sum of all the scores modulo 998244353.

Sample Input 1

4
0 0
0 1
1 0
1 1

Sample Output 1

5

We have five possible sets as S, four sets that form triangles and one set that forms a square. Each of them has a score of 2^0=1, so the answer is 5.

Sample Input 2

5
0 0
0 1
0 2
0 3
1 1

Sample Output 2

11

We have three "triangles" with a score of 1 each, two "triangles" with a score of 2 each, and one "triangle" with a score of 4. Thus, the answer is 11.

Sample Input 3

1
3141 2718

Sample Output 3

0

There are no possible set as S, so the answer is 0.

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Linq;//リストの使用
using System.Collections.Generic;
using System.Text;//テキストの高速出力に必要
class Program
{
	static void Main()
	{
		long n = long.Parse(Console.ReadLine());
    long mod = 998244353;
    long answer = DivideMod(2,n,mod);//2^n

    long[,] vertexes = new long[n,2];//ここに受け取る
    for(long i = 0; i < n; i++)
    {
      long[] nums = Array.ConvertAll(Console.ReadLine().Split(' '),long.Parse);//１行ごとに受け取る
      vertexes[i,0] = nums[0];
      vertexes[i,1] = nums[1];
    }

    //Console.WriteLine(answer);
    answer -= 1;//0個選択
    //answer -= n;//1個選択
    //answer -= n*(n-1)/2;//2個選択
    //Console.WriteLine(answer);

      for(int i = 0; i < n; i++)
      {
        for(int j = i+1; j < n; j++)
        {
          long memo = 0;
          for(int k = 0; k < n; k++)
          {
            Vector2 vecA = new Vector2(vertexes[i,0], vertexes[i,1]);
            Vector2 vecB = new Vector2(vertexes[j,0], vertexes[j,1]);
            Vector2 vecC = new Vector2(vertexes[k,0], vertexes[k,1]);
            if(Vector2.WhereVector(vecA,vecB,vecC) == 3)//線分上の点
            {
              memo++;
            }
          }
            memo += 2;
            answer -= DivideMod(2,memo,mod) - memo - 1;
            //Console.WriteLine(answer);
        }
      }

      answer %= mod;
      if(answer < 0) answer += mod;

		Console.WriteLine(answer);
	}

  static long DivideMod(long x, long a, long p)//戻り値はx^a(mod p)
  {
    long num = 2;
    long answer = 1;
    long check = a;
    long memo = x%p;
    
    while(check > 0)
    {
      if(check % num == num / 2)
      {
        check -= num / 2;
        answer *= memo;
        answer %= p;
      }
    memo *= memo;
    memo %= p;
    num *= 2;
    }
    return answer;
  }
}

class Vector2//2次元ベクトル
{
  static decimal EPS = 1e-10m;//小数誤差比較

  public Vector2 (decimal X, decimal Y)
  {
    this.x = X;
    this.y = Y;
  }

  public decimal x {private set; get;}
  public decimal y {private set; get;}

  public static Vector2 operator + (Vector2 ob1, Vector2 ob2)//ベクトルの基本演算
  {
    return new Vector2 (ob1.x + ob2.x, ob1.y + ob2.y);
  }
  public static Vector2 operator - (Vector2 ob1, Vector2 ob2)
  {
    return new Vector2 (ob1.x - ob2.x, ob1.y - ob2.y);
  }
  public static Vector2 operator * (Vector2 ob, decimal scalar)
  {
    return new Vector2 (ob.x * scalar, ob.y * scalar);
  }
  public static Vector2 operator * (decimal scalar, Vector2 ob)
  {
    return new Vector2 (ob.x * scalar, ob.y * scalar);
  }
  public static Vector2 operator / (Vector2 ob, decimal scalar)
  {
    return new Vector2 (ob.x / scalar, ob.y / scalar);
  }

  public decimal Length()//ベクトルの長さの2乗
  {
    return x * x + y * y;
  }
  public static decimal Distance(Vector2 ob1, Vector2 ob2)//2点間の距離
  {
    return (decimal)Math.Sqrt((double)((ob1.x-ob2.x) * (ob1.x-ob2.x) + (ob1.y-ob2.y) * (ob1.y-ob2.y)));
  }
  public static decimal DotProduct(Vector2 ob1, Vector2 ob2)//内積
  {
    return ob1.x * ob2.x + ob1.y * ob2.y;
  }
  public static decimal CrossProduct(Vector2 ob1, Vector2 ob2)//外積。第2引数が反時計回り側で正。
  {
    return ob1.x * ob2.y - ob1.y * ob2.x;
  }
  public static decimal Arg(Vector2 p)//x軸に対する偏角
  {
    return (decimal)Math.Atan2((double)p.y, (double)p.x);
  }
  public static Vector2 PoralCoordinate(decimal radius, decimal angle)//長さと座標から極座標にする
  {
    return new Vector2(radius * (decimal)Math.Cos((double)angle), radius * (decimal)Math.Sin((double)angle));
  }

  public static Vector2 Projection(Vector2 beginPoint, Vector2 endPoint, Vector2 point)//点の射影
  {
    Vector2 segment = endPoint - beginPoint;
    decimal ratio = Vector2.DotProduct(point - beginPoint, segment) / segment.Length();
    return beginPoint + segment * ratio;//始点にたす
  }

public static long WhereVector(Vector2 beginPoint, Vector2 endPoint, Vector2 point)
  {//ベクトルに対する点の位置
    Vector2 segment = endPoint - beginPoint;
    Vector2 aimVec = point - beginPoint;
    if(Vector2.CrossProduct(segment, aimVec) > 0)
      return 1;//反時計回り側
    else if(Vector2.CrossProduct(segment, aimVec) < 0)
      return 2;//時計回り側
    else if(Vector2.DotProduct(segment, aimVec) < -1+EPS)
      return 3;//ベクトル反対向きの側
    else if(segment.Length() < aimVec.Length())
      return 4;//ベクトル向きの側
    else
      return 5;//ベクトル上
  }

  public static long IsIntersect(Vector2 vecA, Vector2 vecB,
    Vector2 vecAsub, Vector2 vecBsub)//2線分の交差判定
  {
    bool answer = false;

    if(Vector2.WhereVector(vecA, vecB, vecAsub) + Vector2.WhereVector(vecA, vecB, vecBsub) == 3
    && Vector2.WhereVector(vecAsub, vecBsub, vecA) + Vector2.WhereVector(vecAsub, vecBsub, vecB) == 3)
      answer = true;
    if(Vector2.WhereVector(vecA, vecB, vecAsub) == 5 || Vector2.WhereVector(vecA, vecB, vecBsub) == 5
    || Vector2.WhereVector(vecAsub, vecBsub, vecA) == 5 || Vector2.WhereVector(vecAsub, vecBsub, vecB) == 5)
      answer = true;
    return((answer) ? 1 : 0);
  }
  
}