#include <vector>
#include <iostream>
#include <unordered_map>
#include <map>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <cassert>
#include <cmath>
#include <string>
#include <sstream>
using namespace std;

#ifndef MDEBUG
#define NDEBUG
#endif

#define x first
#define y second
#define ll long long
#define d double
#define ld long double
#define pii pair<int,int>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pll pair<ll,ll>
#define pss pair<string,string>
#define psi pair<string,int>
#define pis pair<int,string>
#define psl pair<string,ll>
#define pls pair<ll,string>
#define wh(x) (x).begin(),(x).end()
#define ri(x) int x;cin>>x;
#define rii(x,y) int x,y;cin>>x>>y;
#define rl(x) ll x;cin>>x;
#define rv(v) for(auto&_cinv:v) cin>>_cinv;
#define wv(v) for(auto&_coutv:v) cout << _coutv << ' '; cout << endl;
#define ev(v) for(auto&_cerrv:v) cerr << _cerrv << ' '; cerr << endl;
#define MOD 1000000007

namespace std { 
template<typename T,typename U>struct hash<pair<T,U>>{hash<T>t;hash<U>u;size_t operator()(const pair<T,U>&p)const{return t(p.x)^(u(p.y)<<7);}};
}
// auto fraclt = [](auto&a,auto&b) { return (ll)a.x * b.y < (ll)b.x * a.y; };
template<typename T,typename F>T bsh(T l,T h,const F&f){T r=-1,m;while(l<=h){m=(l+h)/2;if(f(m)){l=m+1;r=m;}else{h=m-1;}}return r;}
template<typename T,typename F>T bsl(T l,T h,const F&f){T r=-1,m;while(l<=h){m=(l+h)/2;if(f(m)){h=m-1;r=m;}else{l=m+1;}}return r;}
template<typename T> T gcd(T a,T b) { if (a<b) swap(a,b); return b?gcd(b,a%b):a; }
template<typename T> void fracn(pair<T,T>&a) {auto g=gcd(a.x,a.y);a.x/=g;a.y/=g;}
template<typename T> struct Index { int operator[](const T&t){auto i=m.find(t);return i!=m.end()?i->y:m[t]=m.size();}int s(){return m.size();} unordered_map<T,int> m; };

template <int N> class Field {
    inline int mod(int i) {int tmp=i%N; return tmp ? i>=0?tmp:tmp+N : 0;}
    inline int mod(ll i) {int tmp=i%N; return tmp ? i>=0?tmp:tmp+N : 0;}
    inline int inv(int a) {
        int t=0,nt=1,r=N,nr=a;
        while(nr) { int q=r/nr; t-=q*nt; swap(t,nt); r-=q*nr; swap(r,nr); }
        assert(r<=1); return (t<0) ? t+N : t;
    }
public:
    inline Field(int x = 0) : v(mod(x)) {}
    inline Field<N>&operator+=(const Field<N>&o) {v=mod(v+o.v); return *this; } 
    inline Field<N>&operator-=(const Field<N>&o) {v=mod(v-o.v); return *this; } 
    inline Field<N>&operator*=(const Field<N>&o) {v=mod((ll)v*o.v); return *this; }
    inline Field<N>&operator/=(const Field<N>&o) { return *this*=inv(o.v); }
    inline Field<N> operator+(const Field<N>&o) {Field<N>r(*this);return r+=o;}
    inline Field<N> operator-(const Field<N>&o) {Field<N>r(*this);return r-=o;}
    inline Field<N> operator*(const Field<N>&o) {Field<N>r(*this);return r*=o;}
    inline Field<N> operator/(const Field<N>&o) {Field<N>r(*this);return r/=o;}
    inline Field<N> operator-() {return {-v};};
    inline Field<N>& operator++() { ++v; if (v==N) v=0; return *this; }
    inline Field<N> operator++(int) { Field<N>r(*this); ++*this; return r; }
    inline Field<N>& operator--() { --v; if (v==-1) v=N-1; return *this; }
    inline Field<N> operator--(int) { Field<N>r(*this); --*this; return r; }
    inline bool operator==(const Field<N>&o) { return o.v==v; }
    inline explicit operator int() const { return v; }
private: int v;
};
template<int N>istream &operator>>(istream&is,Field<N>&f){int v;is>>v;f=v;return is;}
template<int N>ostream &operator<<(ostream&os,const Field<N>&f){return os<<(int)f;}

#define ZM Field<MOD>

vector<ZM> F, I;

int T[1<<16][10];
ZM W[41][(1<<16)+1];

void calcTran(int X, int Y, int Z) {
    int N = X+Y+Z; 
    int S = 1<<(N-1);
    for (int i = 0; i < S; i++) {
        for (int j = 1; j <= 10; j++) {
            int ans = 0;
            for (int k = 0; k <= N; k++) {
                if (k == 0 || (i & (1 << (k-1)))) {
                    if (k < X && k+j <= X) ans |= 1 << (k+j-1);
                    else if (k >= X && k < X+Y && k+j <= X+Y) ans |= 1 << (k+j-1);
                    else if (k >= X+Y && k < X+Y+Z && k+j <= X+Y+Z) ans |= 1 << (k+j-1); 
                }
            }
            if (ans & S) { ans = S; 
                //cout << "FOUND" << i << ' ' << j << endl;
            }
            T[i][j-1] = ans;
            //if (i == 0)
            //cout << "Trans " << i << ' ' << j << '=' << ans << endl;
        }
    }
}



ZM ways(int o, ZM q) {
    assert(o <= (int)q);
    q -= o;
    cout << o << 'c' << q << endl;
    ZM r = F[o-1+(int)q] * I[o-1] * I[(int)q];
    cout << F[o-1+(int)q] << '*' << I[o-1] << '*' << I[(int)q] << '=' << r << endl;
    return r;
}

int main(int,char**) {
    ios_base::sync_with_stdio(false);

    ri(N); ri(X); ri(Y); ri(Z);
    calcTran(X,Y,Z);
    int S = 1 << (X+Y+Z-1);
    for (int i = 0; i <= N; i++) {
    for (int j = 0; j < S; j++) {
        W[i][j] = 0;
    }
    }
    W[0][0] = 1;

    for (int i = 1; i <= N; i++) {
        for (int j = 0; j < S; j++) {
            if (W[i-1][j] == 0) continue;
            //cout << i << ' ' << j << '=' << W[i-1][j] << endl;
            for (int k = 0; k < 10; k++) {
                int t = T[j][k];
                //cout << i << ' ' << j << ' ' << k << '=' << t << endl;
                W[i][t] += W[i-1][j];
            }
        }
        W[i][S] += W[i-1][S] * 10;
    }
    cout << W[N][S] << endl;
   /* int C = 45;
    F.resize(C); I.resize(C);
    F[0] = F[1] = I[0] = I[1] = 1;
    for (int i = 2; i <= C; i++) {
        F[i] = F[i-1] * i;
        I[i] = I[i-1] / i;
        assert(F[i] * I[i] == 1);
    }

    ZM ans = 0;
    for (int x = 0; x <= N-3; x++) {
        for (int y = x+1; y <= min(x+X+1,N-2); y++) {
            for (int z = y+1; z <= min(y+Y+1,N-1); z++) {
                for (int w = z+1; w <= min(z+Z+1,N); w++) {
                    ans += ways(y-x, X) * ways(z-y,Y) * ways(w-z,Z);              
                }
            }
        }
    }*/
}


Measured memory_bytes: 13312