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 Rust (1.15.1) (judge verdict: Wrong Answer)

use std::io::*;
use std::str::FromStr;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

#[allow(dead_code)]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
struct Point {
    x: f64,
    y: f64,
}
#[allow(dead_code)]
type Polygon = Vec<Point>;

impl std::cmp::Eq for Point {}
impl std::cmp::Ord for Point {
    fn cmp(&self, rhs: &Point) -> std::cmp::Ordering {
        (self.x, self.y).partial_cmp(&(rhs.x, rhs.y)).unwrap()
    }
}
impl std::ops::Add for Point {
    type Output = Point;
    fn add(self, rhs: Point) -> Point {
        Point {
            x: self.x + rhs.x,
            y: self.y + rhs.y,
        }
    }
}
impl std::ops::AddAssign for Point {
    fn add_assign(&mut self, rhs: Point) {
        self.x += rhs.x;
        self.y += rhs.y;
    }
}
impl std::ops::Sub for Point {
    type Output = Point;
    fn sub(self, rhs: Point) -> Point {
        Point {
            x: self.x - rhs.x,
            y: self.y - rhs.y,
        }
    }
}
impl std::ops::SubAssign for Point {
    fn sub_assign(&mut self, rhs: Point) {
        self.x -= rhs.x;
        self.y -= rhs.y;
    }
}
impl std::ops::Mul<Point> for f64 {
    type Output = Point;
    fn mul(self, rhs: Point) -> Point {
        Point {
            x: self * rhs.x,
            y: self * rhs.y,
        }
    }
}
impl std::ops::Mul<f64> for Point {
    type Output = Point;
    fn mul(self, rhs: f64) -> Point {
        Point {
            x: self.x * rhs,
            y: self.y * rhs,
        }
    }
}
impl std::ops::Div<f64> for Point {
    type Output = Point;
    fn div(self, rhs: f64) -> Point {
        Point {
            x: self.x / rhs,
            y: self.y / rhs,
        }
    }
}
#[allow(dead_code)]
impl Point {
    fn new(x: f64, y: f64) -> Point {
        Point { x: x, y: y }
    }
    fn norm(&self) -> f64 {
        (self.x * self.x + self.y * self.y).sqrt()
    }
}
#[allow(dead_code)]
fn cross(lhs: &Point, rhs: &Point) -> f64 {
    lhs.x * rhs.y - lhs.y * rhs.x
}
#[allow(dead_code)]
fn dot(lhs: &Point, rhs: &Point) -> f64 {
    lhs.x * rhs.x + lhs.y * rhs.y
}
#[allow(dead_code)]
fn ccw(a: &Point, b: &Point, c: &Point) -> i32 {
    let b = *b - *a;
    let c = *c - *a;
    if cross(&b, &c) > 0f64 {
        return 1; // ccw
    }
    if cross(&b, &c) < 0f64 {
        return -1; // cw
    }
    if dot(&b, &c) < 0f64 {
        return 2; // online & reverse direction
    }
    if b.norm() < c.norm() {
        return -2; // online & same direction & |b| < |c|
    }
    0 // online & same direction & b| > |c|
}

#[allow(dead_code)]
#[derive(Eq, PartialEq)]
enum ContainState {
    OUT,
    ON,
    IN,
}
#[allow(dead_code)]
fn contain_point(poly: &Polygon, p: &Point) -> ContainState {
    let mut inner = false;
    for i in 0..poly.len() {
        let mut a = poly[i] - *p;
        let mut b = poly[(i + 1) % poly.len()] - *p;
        if a.y > b.y {
            std::mem::swap(&mut a, &mut b);
        }
        if a.y <= 0f64 && 0f64 < b.y {
            if cross(&a, &b) < 0f64 {
                inner = !inner;
            }
        }
        if cross(&a, &b) == 0f64 && dot(&a, &b) <= 0f64 {
            return ContainState::ON;
        }
    }
    if inner {
        ContainState::IN
    } else {
        ContainState::OUT
    }
}

#[test]
fn test_add_sub() {
    let p1 = Point::new(1f64, 2f64);
    let p2 = Point::new(10f64, 20f64);
    let p3 = p1 + p2;
    assert!(p3.x == 11f64);
    assert!(p3.y == 22f64);
    let p4 = p3 - p2;
    assert!(p4 == p1);
    let mut p5 = p1;
    p5 += p2;
    assert!(p3 == p5);
    let mut p6 = p3;
    p6 -= p2;
    assert!(p6 == p1);
}
#[test]
fn test_mul_div() {
    let p1 = Point::new(1f64, 2f64);
    let v = 10f64;
    let p2 = v * p1;
    assert!(p2.x == 10f64);
    assert!(p2.y == 20f64);
    let p3 = p2 / 10f64;
    assert!(p3.x == 1f64);
    assert!(p3.y == 2f64);
}
#[test]
fn test_cross_dot() {
    let p1 = Point::new(1f64, 2f64);
    let p2 = Point::new(3f64, -7f64);
    assert!(dot(&p1, &p2) == -11f64);
    assert!(cross(&p1, &p2) == -13f64);
}
#[test]
fn test_ccw() {
    let p1 = Point::new(1f64, 1f64);
    let p2 = Point::new(2f64, 1f64);
    let p3 = Point::new(1f64, 2f64);
    assert!(ccw(&p1, &p2, &p3) == 1);
    assert!(ccw(&p1, &p3, &p2) == -1);
    assert!(ccw(&p1, &p2, &p2) == 0);
}
#[test]
fn test_contain_point() {
    let p1 = Point::new(0f64, 0f64);
    let p2 = Point::new(0f64, 3f64);
    let p3 = Point::new(3f64, 0f64);
    let poly: Polygon = vec![p1, p2, p3];
    let p4 = Point::new(1f64, 1f64);
    let p5 = Point::new(1f64, 0f64);
    let p6 = Point::new(3f64, 3f64);
    assert!(contain_point(&poly, &p4) == ContainState::IN);
    assert!(contain_point(&poly, &p5) == ContainState::ON);
    assert!(contain_point(&poly, &p6) == ContainState::OUT);
}

fn main() {
    let n = read::<usize>();
    let mut ps = vec![Point::new(0f64, 0f64); n];
    for i in 0..n {
        let x = read::<f64>();
        let y = read::<f64>();
        ps[i] = Point::new(x, y);
    }
    let mut cnts = vec![vec![vec![0; n]; n]; n];
    for i in 0..n {
        for j in i + 1..n {
            for k in j + 1..n {
                let poly = vec![ps[i], ps[j], ps[k]];
                let mut cnt = 0;
                for l in 0..n {
                    if contain_point(&poly, &ps[l]) != ContainState::OUT {
                        cnt += 1;
                    }
                }
                cnt -= 3;
                cnts[i][j][k] = cnt;
                cnts[i][k][j] = cnt;
                cnts[j][i][k] = cnt;
                cnts[j][k][i] = cnt;
                cnts[k][i][j] = cnt;
                cnts[k][j][i] = cnt;
            }
        }
    }
}