Problem:
Score : 700 points

Problem Statement

Haiku is a short form of Japanese poetry. A Haiku consists of three phrases with 5, 7 and 5 syllables, in this order.

Iroha is looking for X,Y,Z-Haiku (defined below) in integer sequences.

Consider all integer sequences of length N whose elements are between 1 and 10, inclusive. Out of those 10^N sequences, how many contain an X,Y,Z-Haiku?

Here, an integer sequence a_0, a_1, ..., a_{N-1} is said to contain an X,Y,Z-Haiku if and only if there exist four indices x, y, z, w (0 ≦ x < y < z < w ≦ N) such that all of the following are satisfied:

a_x + a_{x+1} + ... + a_{y-1} = X

a_y + a_{y+1} + ... + a_{z-1} = Y

a_z + a_{z+1} + ... + a_{w-1} = Z

Since the answer can be extremely large, print the number modulo 10^9+7.

Constraints

3 ≦ N ≦ 40

1 ≦ X ≦ 5

1 ≦ Y ≦ 7

1 ≦ Z ≦ 5

Input

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

N X Y Z

Output

Print the number of the sequences that contain an X,Y,Z-Haiku, modulo 10^9+7.

Sample Input 1

3 5 7 5

Sample Output 1

1

Here, the only sequence that contains a 5,7,5-Haiku is [5, 7, 5].

Sample Input 2

4 5 7 5

Sample Output 2

34

Sample Input 3

37 4 2 3

Sample Output 3

863912418

Sample Input 4

40 5 7 5

Sample Output 4

562805100

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

// ---------- begin Aho-Corasick ----------
const F: usize = 11;

struct ACTrieNode {
    fail: usize,
    next: [usize; F],
}

impl ACTrieNode {
    fn new() -> ACTrieNode {
        ACTrieNode {
            fail: 0,
            next: [0; F],
        }
    }
}

struct AhoCorasick {
    node: Vec<ACTrieNode>,
}

#[allow(dead_code)]
impl AhoCorasick {
    fn new() -> Self {
        let root = ACTrieNode::new();
        AhoCorasick {
            node: vec![root],
        }
    }
    fn insert(&mut self, s: &Vec<usize>) -> usize {
        let node = &mut self.node;
        let mut v = 0;
        for &k in s {
            if node[v].next[k] == 0 {
                node[v].next[k] = node.len();
                let t = ACTrieNode::new();
                node.push(t);
            }
            v = node[v].next[k];
        }
        v
    }
    fn build(&mut self) {
        let mut q = std::collections::VecDeque::new();
        let node = &mut self.node;
        for i in 0..F {
            if node[0].next[i] != 0 {
                q.push_back(node[0].next[i]);
            }
        }
        while let Some(v) = q.pop_front() {
            for i in 0..F {
                let u = node[v].next[i];
                let mut fail = node[v].fail;
                if u == 0 {
                    node[v].next[i] = node[fail].next[i];
                    continue;
                }
                while fail > 0 && node[fail].next[i] == 0 {
                    fail = node[fail].fail;
                }
                let f = node[fail].next[i];
                node[u].fail = f;
                q.push_back(u);
            }
        }
    }
    fn next(&self, v: usize, k: usize) -> usize {
        self.node[v].next[k]
    }
    fn trans(&self, mut v: usize, k: usize) -> usize {
        let node = &self.node;
        while v > 0 && node[v].next[k] == 0 {
            v = node[v].fail;
        }
        node[v].next[k]
    }
    fn fail(&self, k: usize) -> usize {
        self.node[k].fail
    }
    fn get_size(&self) -> usize {
        self.node.len()
    }
}
// ---------- end Aho-Corasick ----------
// ---------- begin ModInt ----------
const MOD: u32 = 1_000_000_007;

#[derive(Clone, Copy)]
struct ModInt(u32);

impl std::ops::Add for ModInt {
    type Output = ModInt;
    fn add(self, rhs: ModInt) -> Self::Output {
        let mut d = self.0 + rhs.0;
        if d >= MOD {
            d -= MOD;
        }
        ModInt(d)
    }
}

impl std::ops::AddAssign for ModInt {
    fn add_assign(&mut self, rhs: ModInt) {
        *self = *self + rhs;
    }
}

impl std::ops::Sub for ModInt {
    type Output = ModInt;
    fn sub(self, rhs: ModInt) -> Self::Output {
        let mut d = self.0 + MOD - rhs.0;
        if d >= MOD {
            d -= MOD;
        }
        ModInt(d)
    }
}

impl std::ops::SubAssign for ModInt {
    fn sub_assign(&mut self, rhs: ModInt) {
        *self = *self - rhs;
    }
}

impl std::ops::Mul for ModInt {
    type Output = ModInt;
    fn mul(self, rhs: ModInt) -> Self::Output {
        ModInt((self.0 as u64 * rhs.0 as u64 % MOD as u64) as u32)
    }
}

impl std::ops::MulAssign for ModInt {
    fn mul_assign(&mut self, rhs: ModInt) {
        *self = *self * rhs;
    }
}

impl std::ops::Neg for ModInt {
    type Output = ModInt;
    fn neg(self) -> Self::Output {
        ModInt(if self.0 == 0 {0} else {MOD - self.0})
    }
}

impl std::fmt::Display for ModInt {
    fn fmt<'a>(&self, f: &mut std::fmt::Formatter<'a>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl std::str::FromStr for ModInt {
    type Err = std::num::ParseIntError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let val = s.parse::<u32>()?;
        Ok(ModInt::new(val))
    }
}

#[allow(dead_code)]
impl ModInt {
    pub fn new(n: u32) -> ModInt {
        ModInt(n % MOD)
    }
    pub fn zero() -> ModInt {
        ModInt(0)
    }
    pub fn one() -> ModInt {
        ModInt(1)
    }
    pub fn pow(self, mut n: u32) -> ModInt {
        let mut t = ModInt::one();
        let mut s = self;
        while n > 0 {
            if n & 1 == 1 {
                t *= s;
            }
            s *= s;
            n >>= 1;
        }
        t
    }
    pub fn inv(self) -> ModInt {
        self.pow(MOD - 2)
    }
}
// ---------- end ModInt ----------
// ---------- begin Precalc ----------
#[allow(dead_code)]
struct Precalc {
    inv: Vec<ModInt>,
    fact: Vec<ModInt>,
    ifact: Vec<ModInt>,
}

#[allow(dead_code)]
impl Precalc {
    pub fn new(n: usize) -> Precalc {
        let mut inv = vec![ModInt::one(); n + 1];
        let mut fact = vec![ModInt::one(); n + 1];
        let mut ifact = vec![ModInt::one(); n + 1];
        for i in 2..(n + 1) {
            inv[i] = -inv[MOD as usize % i] * ModInt(MOD / i as u32);
            fact[i] = fact[i - 1] * ModInt(i as u32);
            ifact[i] = ifact[i - 1] * inv[i];
        }
        Precalc {
            inv: inv,
            fact: fact,
            ifact: ifact,
        }
    }
    pub fn inv(&self, n: usize) -> ModInt {
        self.inv[n]
    }
    pub fn fact(&self, n: usize) -> ModInt {
        self.fact[n]
    }
    pub fn ifact(&self, n: usize) -> ModInt {
        self.ifact[n]
    }
    pub fn comb(&self, n: usize, k: usize) -> ModInt {
        if k > n {
            return ModInt::zero();
        }
        self.fact[n] * self.ifact[k] * self.ifact[n - k]
    }
}
// ---------- end Precalc ----------

fn run() {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    let mut it = s.trim().split_whitespace();
    let n: usize = it.next().unwrap().parse().unwrap();
    let x: usize = it.next().unwrap().parse().unwrap();
    let y: usize = it.next().unwrap().parse().unwrap();
    let z: usize = it.next().unwrap().parse().unwrap();
    let mut state = vec![];
    let mut aho = AhoCorasick::new();
    let mut dfs = vec![(0, vec![])];
    while let Some((sum, a)) = dfs.pop() {
        if sum > x + y + z {
            continue;
        } else if sum == x + y + z {
            let mut i = 0;
            let mut ok = true;
            for &v in [x, y, z].iter() {
                let mut s = 0;
                while i < a.len() && s < v {
                    s += a[i];
                    i += 1;
                }
                if s != v {
                    ok = false;
                }
            }
            if ok {
                let k = aho.insert(&a);
                state.push(k);
            }
        } else {
            for i in 1..11 {
                let mut a = a.clone();
                a.push(i);
                dfs.push((sum + i, a));
            }
        }
    }
    state.sort();
    state.dedup();
    aho.build();
    let mut dp = vec![ModInt::zero(); aho.get_size()];
    let mut next = vec![ModInt::zero(); aho.get_size()];
    dp[0] = ModInt::one();
    let mut ans = ModInt::zero();
    for _ in 0..n {
        next.clear();
        next.resize(aho.get_size(), ModInt::zero());
        for (v, dp) in dp.iter().enumerate() {
            for k in 1..11 {
                let u = aho.next(v, k);
                next[u] += *dp;
            }
        }
        std::mem::swap(&mut dp, &mut next);
        let mut way = ModInt::zero();
        for &v in &state {
            way += dp[v];
            dp[v] = ModInt::zero();
        }
        ans = ModInt(10) * ans + way;
    }
    println!("{}", ans);
}

fn main() {
    run();
}