fn main() {
    input!{
		n: usize, _f: usize,
		a: [u64; n],
		b: [u64; n],
		c: [u64; n],
	}
	
	let mut cur_dp = vec![0u128; n+1];
	cur_dp[0] = 1;

	// mask値を事前計算(下位桁、上位桁)
	let mask1 = (1 << 64)-1;
	let mask2 = !0;

	// i人
	for i in 0..n {
		let mut next_dp = vec![0u128; n+1];
		// 状態j
		for j in 0..=i {
			// 1つ目の手
			let next1 = cur_dp[j] << a[i];
			next_dp[j] |= next1 & mask1;
			next_dp[j+1] |= (next1 & mask2) >> 64;
			// 2つ目の手
			let next2 = cur_dp[j] << b[i];
			next_dp[j] |= next2 & mask1;
			next_dp[j+1] |= (next2 & mask2) >> 64;
			// 3つ目の手
			let next3 = cur_dp[j] << c[i];
			next_dp[j] |= next3 & mask1;
			next_dp[j+1] |= (next3 & mask2) >> 64;
		}
		let mut ret = 0;
		for j in 0..=i {
			ret += next_dp[j].count_ones();
		}
		println!("{}", ret);

		swap(&mut cur_dp, &mut next_dp);
	}
}

// const MOD17: usize = 1000000007;
// const MOD93: usize = 998244353;
// const INF: usize = 1 << 60;
// let dx = vec![!0, 0, 1, 0]; // 上左下右
// let dy = vec![0, !0, 0, 1]; // 上左下右
// let d = vec!{(!0, 0), (0, !0), (1, 0), (0, 1)}; // 上左下右

#[allow(unused)]
use proconio::{input, marker::Chars, marker::Usize1};

#[allow(unused)]
use std::{
	mem::swap,
	cmp::min, cmp::max,
	cmp::Reverse,
	collections::HashSet, collections::BTreeSet,
	collections::HashMap, collections::BTreeMap,
	collections::BinaryHeap,
	collections::VecDeque,
	iter::FromIterator,
};
// 配列のスペース区切り出力
#[allow(unused)]
fn vec_print<T: std::fmt::Display>(vec: &Vec<T>) {
	let sz = vec.len();
	for i in 0..sz-1 {
		print!("{} ", vec[i]);
	}
	println!("{}", vec[sz-1]);
}