///#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
///#pragma GCC target("sse,sse2,sse3,ssse3,sse4,abm,mmx,popcnt,avx,avx2,tune=native")

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

/*
    zet:
        find_by_order(k): k-stat [k > 0]
        order_of_key(k) : {el < k}

    gp_hash_table<key, val, custom_hash>

    rope<T>:
        iterators: mutable_begin, ..
        methods  : erase, insert, substr, ..
*/

#define all(x) (x).begin(), (x).end()
#define size(x) (int)((x).size())
#define em_back emplace_back

using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;

using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

template<typename T>
using zet = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

mt19937 eng(chrono::steady_clock::now().time_since_epoch().count());

using vi = vector<int>;

const int K = 10;
const int mod = 1e9 + 7;

int sum(int a, int b) {
    return (a + b) % mod;
}

int diff(int a, int b) {
    return (a - b + mod) % mod;
}

int mult(int a, int b) {
    return (ll)a * b % mod;
}

int binpow(int a, int b) {
    if (!b) {
        return 1;
    }
    if (b & 1) {
        return mult(a, binpow(a, b ^ 1));
    } else {
        return binpow(mult(a, a), b >> 1);
    }
}

int n, x, y, z;
vi way;

void brute(int sum, int limit, vector<vi>& to) {
    if (sum == limit) {
        to.em_back(way);
        return;
    }

    for (int i = 1; i <= K; ++i) if (sum + i <= limit) {
        way.em_back(i);
        brute(sum + i, limit, to);
        way.pop_back();
    }
}

vector<vi> mstr(int m) {
    vector<vi> res;
    brute(0, m, res);
    return res;
}

vector<vi> words;

void prepare() {
    vector<vi> xstr = mstr(x);
    vector<vi> ystr = mstr(y);
    vector<vi> zstr = mstr(z);

    for (int i = 0; i < size(xstr); ++i) {
        for (int j = 0; j < size(ystr); ++j) {
            for (int k = 0; k < size(zstr); ++k) {
                vi word;
                word.insert(word.end(), all(xstr[i]));
                word.insert(word.end(), all(ystr[j]));
                word.insert(word.end(), all(zstr[k]));
                words.push_back(word);
                for (int& d : words.back()) {
                    d--;
                }
            }
        }
    }
}

struct Node {
    int go[K];
    int p;
    int pc;
    int link;
    bool leaf;

    Node() {
        memset(go, -1, sizeof go);
        link = -1;
        leaf = false;
        p = pc = -1;
    }
};

const int N = 4e4 + 4;

int id = 1, root;
Node nodes[N];

void add(vi w) {
    int u = root;
    for (int i = 0; i < size(w); ++i) {
        int c = w[i];
        int& to = nodes[u].go[c];
        if (to == -1) {
            to = id++;
            Node& here = nodes[to];
            here.p = u;
            here.pc = c;
        }
        u = to;
    }
    nodes[u].leaf = 1;
}

int go(int u, int c);
int suff(int u);

int suff(int u) {
    int& link = nodes[u].link;
    if (link != -1) {
        return link;
    }

    if (u == 0 || nodes[u].p == root) {
        return link = 0;
    }

    return link = go(suff(nodes[u].p), nodes[u].pc);
}

int go(int u, int c) {
    int& res = nodes[u].go[c];
    if (res != -1) {
        return res;
    }

    if (u == 0) {
        return res = 0;
    }

    return res = go(suff(u), c);
}

int dpBlock[N];

int block(int u) {
    int& res = dpBlock[u];
    if (res != -1) {
        return res;
    }
    if (u == root) {
        return res = 0;
    }

    if (nodes[u].leaf) {
        return res = 1;
    }

    return res = block(suff(u));
}

void letsGoAho() {
    for (int i = 0; i < size(words); ++i) {
        add(words[i]);
    }
    for (int i = 0; i < id; ++i) {
        for (int c = 0; c < K; ++c) {
            go(i, c);
        }
        suff(i);
    }

    memset(dpBlock, -1, sizeof dpBlock);
    for (int i = 0; i < id; ++i) {
        block(i);
    }
}

const int LEN = 44;

int dp[LEN][N];

int fdp(int len, int u) {
    int& res = dp[len][u];
    if (res != -1) {
        return res;
    }

    res = 0;

    if (len == 0) {
        return res = 1;
    }

    for (int c = 0; c < K; ++c) if (!block(go(u, c))) {
        res = sum(res, fdp(len - 1, go(u, c)));
    }

    return res;
}

void calc() {
    memset(dp, -1, sizeof dp);
    cout << diff(binpow(10, n), fdp(n, root)) << "\n";
}

void solve() {
    cin >> n >> x >> y >> z;
    prepare();
    letsGoAho();
    calc();
}

int main() {
    ios::sync_with_stdio(0);
    cout.tie(0), cin.tie(0);

    int z = 1;
    /// cin >> z;

    while (z--) {
        solve();
    }

    return 0;
}


Measured memory_bytes: 13732