#include <bits/stdc++.h>
//#include <chrono>
//#pragma GCC optimize("Ofast")
using namespace std;
#define reps(i,s,n) for(int i = s; i < n; i++)
#define rep(i,n) reps(i,0,n)
#define Rreps(i,n,e) for(int i = n - 1; i >= e; --i)
#define Rrep(i,n) Rreps(i,n,0)
#define ALL(a) a.begin(), a.end()
#define fi first
#define se second

using ll = long long;
using vec = vector<ll>;
using mat = vector<vec>;

ll N,M,H,W,Q,K,A,B;
string S;
typedef pair<ll, ll> P;
const ll INF = (1LL<<58);

template <unsigned long long mod > class modint{
public:
    ll x;
    constexpr modint(){x = 0;}
    constexpr modint(ll _x) : x((_x < 0 ? ((_x += (LLONG_MAX / mod) * mod) < 0 ? _x + (LLONG_MAX / mod) * mod : _x) : _x)%mod){}
    constexpr modint set_raw(ll _x){
        //_x in [0, mod)
        x = _x;
        return *this;
    }
    constexpr modint operator-(){
        return x == 0 ? 0 : mod - x;
    }
    constexpr modint& operator+=(const modint& a){
        if((x += a.x) >= mod) x -= mod;
        return *this;
    }
    constexpr modint operator+(const modint& a) const{
        return modint(*this) += a;
    }
    constexpr modint& operator-=(const modint& a){
        if((x -= a.x) < 0) x += mod;
        return *this;
    }
    constexpr modint operator-(const modint& a) const{
        return modint(*this) -= a;
    }
    constexpr modint& operator*=(const modint& a){
        (x *= a.x)%=mod;
        return *this;
    }
    constexpr modint operator*(const modint& a) const{
        return modint(*this) *= a;
    }
    constexpr modint pow(unsigned long long pw) const{
        modint res(1), comp(*this);
        while(pw){
            if(pw&1) res *= comp;
            comp *= comp;
            pw >>= 1;
        }
        return res;
    }
    //以下、modが素数のときのみ
    constexpr modint inv() const{
        if(x == 2) return (mod + 1) >> 1;
        return modint(*this).pow(mod - 2);
    }
    constexpr modint& operator/=(const modint &a){
        (x *= a.inv().x)%=mod;
        return *this;
    }
    constexpr modint operator/(const modint &a) const{
        return modint(*this) /= a;
    }
};
#define mod2 1000000007
using mint = modint<mod2>;

ostream& operator<<(ostream& os, const mint& a){
    os << a.x;
    return os;
}
using vm = vector<mint>;

template <int _char_size>
struct Trie{
    struct node{
        int parent;
        bool flag_end;
        vector<int> to;
        bitset<_char_size> ok;
        node(int _p = -1) : parent(_p), flag_end(false), to(_char_size, -1), ok(0){}
    };
    int tree_size;
    vector<node> tree;
    Trie() : tree_size(1), tree(1) {}
    void append(vector<int> &a, bool rev = false){
        int s(0), n(a.size());
        rep(i, n){
            tree[s].ok[a[rev ? n - 1 - i : i]] = true;
            int &to = tree[s].to[a[rev ? n - 1 - i : i]];
            if(to == -1) {
                to = tree_size++;
                tree.emplace_back(s);
            }
            s = to;
        }
        tree[s].flag_end = true;
    }
    int search(vector<int> &a, int s = 0){
        int v(0), n(a.size());
        reps(i, s, n){
            int &to = tree[v].to[a[i]];
            if(to == -1 || !tree[v].ok[a[i]]) return -1;
            v = to;
        }
        return v;
    }
    int find_id(vector<int> &v){
        int n(v.size());
        reps(i, 1, n){
            int temp = search(v, i);
            if(temp != -1) return temp;
        }
        return 0;
    }
    void dfs(int now, vector<int> &v){
        rep(i, _char_size){
            int &to = tree[now].to[i];
            v.push_back(i);
            if(to == -1){
                to = find_id(v);
            }else if(!tree[to].flag_end){
                dfs(to, v);
            }
            v.pop_back();
        }
    }
    void fill(){
        vector<int> now_v(0);
        dfs(0, now_v);
    }
    bool step(int &id, int a){
        id = tree[id].to[a]; //-1は無いように処理しておく
        if(tree[id].flag_end) return false;
        return true;
    }
};

int X, Y, Z;
void make_v(int len, int s, vector<int> &res){
    int now(0);
    rep(i, len-1){
        if((s>>i)&1){
            res.push_back(now);
            now = 0;
        }else{
            ++now;
        }
    }
    res.push_back(now);
}
void make_trie(Trie<10> &T){
    rep(s, 1<<(X-1)){
        vector<int> v1(0);
        make_v(X, s, v1);
        rep(t, 1<<(Y-1)){
            vector<int> v2(v1);
            make_v(Y, t, v2);
            rep(u, 1<<(Z-1)){
                vector<int> v3(v2);
                make_v(Z, u, v3);
                T.append(v3);
            }
        }
    }
}

int main() {
    cin>>N>>X>>Y>>Z;
    Trie<10> T;
    make_trie(T);
    T.fill();
    vector<vm> dp(N + 1, vm(T.tree_size, 0));
    dp[0][0] = 1;
    rep(i, N){
        rep(j, T.tree_size){
            if(T.tree[j].flag_end) continue;
            rep(k, 10){
                int to(j);
                if(T.step(to, k)) dp[i+1][to] += dp[i][j];
            }
        }
    }
    mint res = mint(10).pow(N);
    rep(i, T.tree_size) res -= dp[N][i];
    cout<<res<<endl;
}


Measured memory_bytes: 17188