Problem:
Score : 1000 points

Problem Statement

We will host a rock-paper-scissors tournament with N people. The participants are called Person 1, Person 2, \ldots, Person N.
For any two participants, the result of the match between them is determined in advance.
This information is represented by positive integers A_{i,j} ( 1 \leq j < i \leq N ) as follows:

If A_{i,j} = 0, Person j defeats Person i.

If A_{i,j} = 1, Person i defeats Person j.

The tournament proceeds as follows:

We will arrange the N participants in a row, in the order Person 1, Person 2, \ldots, Person N from left to right.

We will randomly choose two consecutive persons in the row. They will play a match against each other, and we will remove the loser from the row.
We will repeat this process N-1 times, and the last person remaining will be declared the champion.

Find the number of persons with the possibility of becoming the champion.

Constraints

1 \leq N \leq 2000

A_{i,j} is 0 or 1.

Input

Input is given from Standard Input in the following format:

N
A_{2,1}
A_{3,1}A_{3,2}
:
A_{N,1}\ldotsA_{N,N-1}

Output

Print the number of persons with the possibility of becoming the champion.

Sample Input 1

3
0
10

Sample Output 1

2

Person 1 defeats Person 2, Person 2 defeats Person 3 and Person 3 defeats Person 1.
If Person 1 and Person 2 play the first match, Person 3 will become the champion.
If Person 2 and Person 3 play the first match, Person 1 will become the champion.

Sample Input 2

6
0
11
111
1111
11001

Sample Output 2

3

Solution in Rust (1.15.1) (judge verdict: Accepted)

// https://atcoder.jp/contests/m-solutions2019/tasks/m_solutions2019_f
//
#![allow(unused_imports)]
use std::io::*;
use std::io::Write;
use std::fmt::*;
use std::str::*;
use std::cmp::*;
use std::collections::*;

// Input macros.
// Original by tanakh: https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
#[allow(unused_macros)]
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };

    ($iter:expr, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($iter:expr, [ next / $t:tt ]) => {
        {
            let len = read_value!($iter, usize);
            (0..len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
        }
    };

    ($iter:expr, switch) => {
        {
            let ty = read_value!($iter, i32);
            if ty == 1 {
                vec![ty, read_value!($iter, i32), read_value!($iter, i32)]
            } else if ty == 2 {
                vec![ty, read_value!($iter, i32)]
            } else {
                vec![ty, read_value!($iter, i32)]
            }
        }
    };

    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

#[allow(unused_macros)]
macro_rules! read_line {
    ($t:tt) => {
        {
            let mut s = String::new();
            std::io::stdin().read_line(&mut s).unwrap();
            s.trim_right().parse::<$t>().unwrap()
        }
    }
}

#[allow(unused_macros)]
macro_rules! dvec {
    ($t:expr ; $len:expr) => {
        vec![$t; $len]
    };

    ($t:expr ; $len:expr, $($rest:expr),*) => {
        vec![dvec!($t; $($rest),*); $len]
    };
}

#[allow(unused_macros)]
macro_rules! ifv {
    ($t:expr, $a:expr, $b: expr) => {
        if $t { $a } else { $b }
    }
}

#[allow(unused_macros)]
macro_rules! fill {
    ($t:expr, $v:expr) => {
        for i in 0..$t.len() {
            $t[i] = $v;
        }
    };
}

#[allow(unused_macros)]
macro_rules! join {
    ($t:expr, $glue:expr) => {
        $t.into_iter().map(|w| w.to_string()).collect::<Vec<_>>().join($glue)
    };
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($a:expr),*) => {
        println!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
    }
}


// ===


#[derive(Clone, Debug)]
struct BitVector {
    n: usize,
    size: usize,
    data: Vec<u64>
}

impl BitVector {
    fn new(n: usize) -> Self {
        let size = (n+63)/64;
        BitVector {
            n: n,
            size: size,
            data: vec![0; size]
        }
    }

    fn get(&self, i: usize) -> bool {
        self.data[i/64]>>(i%64) & 1 != 0
    }

    fn set(&mut self, i: usize) {
        self.data[i/64] |= 1<<(i%64);
    }

    fn count(&self) -> usize {
        let mut cnt = 0;
        for i in 0..self.size {
            cnt += self.data[i].count_ones();
        }
        cnt as usize
    }
}

impl<'a> std::ops::Shl<usize> for &'a BitVector {
    type Output = BitVector;

    fn shl(self, amount: usize) -> Self::Output {
        let mut new_vector = BitVector::new(self.n);

        let diff = amount / 64;
        let diff_mod = amount % 64;
        if diff_mod == 0 {
            for i in 0..self.size-diff {
                new_vector.data[i+diff] = self.data[i];
            }
        } else {
            let lower_mask = (1<<(64-diff_mod))-1;
            let upper_mask = ((1<<diff_mod)-1)<<(64-diff_mod);
            for i in 0..self.size-diff {
                new_vector.data[i+diff] |= (self.data[i] & lower_mask)<<diff_mod;
                if i+diff+1 < self.size {
                    new_vector.data[i+diff+1] |= (self.data[i] & upper_mask)>>(64-diff_mod);
                }
            }
        }
        new_vector
    }
}


impl<'a> std::ops::Shr<usize> for &'a BitVector {
    type Output = BitVector;

    fn shr(self, amount: usize) -> Self::Output {
        let mut new_vector = BitVector::new(self.n);

        let diff = amount / 64;
        let diff_mod = amount % 64;
        if diff_mod == 0 {
            for i in diff..self.size {
                new_vector.data[i-diff] = self.data[i];
            }
        } else {
            let lower_mask = (1<<diff_mod)-1;
            let upper_mask = ((1<<(64-diff_mod))-1)<<diff_mod;
            for i in diff..self.size {
                new_vector.data[i-diff] |= (self.data[i] & upper_mask)>>diff_mod;
                if i > diff {
                    new_vector.data[i-diff-1] |= (self.data[i] & lower_mask)<<(64-diff_mod);
                }
            }
        }
        new_vector
    }
}

impl<'a> std::ops::BitAnd for &'a BitVector {
    type Output = BitVector;

    fn bitand(self, other: Self) -> Self::Output {
        let mut output = BitVector::new(self.n);
        for i in 0..self.size {
            output.data[i] = self.data[i] & other.data[i];
        }
        output
    }
}

impl std::ops::BitAndAssign for BitVector {
    fn bitand_assign(&mut self, rhs: Self) {
        for i in 0..min(self.size, rhs.size) {
            self.data[i] &= rhs.data[i];
        }
    }
}

impl<'a> std::ops::BitOr for &'a BitVector {
    type Output = BitVector;

    fn bitor(self, other: Self) -> Self::Output {
        let mut output = BitVector::new(self.n);
        for i in 0..self.size {
            output.data[i] = self.data[i] | other.data[i];
        }
        output
    }
}

impl std::ops::BitOrAssign for BitVector {
    fn bitor_assign(&mut self, rhs: Self) {
        for i in 0..min(self.size, rhs.size) {
            self.data[i] |= rhs.data[i];
        }
    }
}

impl std::ops::BitXorAssign for BitVector {
    fn bitxor_assign(&mut self, rhs: Self) {
        for i in 0..min(self.size, rhs.size) {
            self.data[i] ^= rhs.data[i];
        }
    }
}

//===

fn main() {
    input! {
        n: usize,
        table: [chars; n-1]
    };

    // 1 to n, 0 and n+1 are sentinels
    let mut wintable = vec![BitVector::new(2048); n+2];
    for i in 2..n+1 {
        for j in 1..i {
            if table[i-2][j-1] == '1' {
                // i wins j
                wintable[i].set(j);
            } else {
                wintable[j].set(i);
            }
        }
    }

    let mut dp_left = vec![BitVector::new(2048); n+2];
    let mut dp_right = vec![BitVector::new(2048); n+2];

    let mut dp_left_rev = vec![BitVector::new(2048); n+2];
    let mut dp_right_rev = vec![BitVector::new(2048); n+2];

    for i in 1..n+1 {
        dp_left[i].set(i);
        dp_right[i].set(i);
        dp_left_rev[i].set(i);
        dp_right_rev[i].set(i);
    }
    for l in 1..n {
        for i in 1..n+1 {
            if i > l {
                let lj = i-l;
                let mut ok = false;
                ok |= (&dp_left[i] & &dp_left_rev[lj]).count() >= 1;
                ok |= (&(&(&dp_left[i]>>1) & &dp_left_rev[lj]) & &wintable[i]).count() >= 1;
                ok |= wintable[i].get(lj) && (&dp_left[i] & &(&dp_right[lj]<<1)).count() >= 1;
                if ok {
                    dp_left[i].set(lj);
                    dp_left_rev[lj].set(i);
                }
            }
            if i+l <= n {
                let rj = i+l;
                let mut ok = false;
                ok |= (&dp_right[i] & &dp_right_rev[rj]).count() >= 1;
                ok |= (&(&(&dp_right[i]<<1) & &dp_right_rev[rj]) & &wintable[i]).count() >= 1;
                ok |= wintable[i].get(rj) && (&dp_right[i] & &(&dp_left[rj]>>1)).count() >= 1;
                if ok {
                    dp_right[i].set(rj);
                    dp_right_rev[rj].set(i);
                }
            }
        }
    }


    let mut count = 0;
    for i in 1..n+1 {
        if dp_left[i].get(1) && dp_right[i].get(n) {
            count += 1;
            // debug!(i);
        }
    }
    println!("{}", count);
}