#include <functional>
#include <cstdlib>
#include <cstdio>
#include <array>
#include <map>
#include <algorithm>
#include <iterator>
#include <vector>
namespace XX
{   
    template<template<typename> class Compare, typename T>
    inline T& UP(T& x, const T& y){if(Compare<T>()(y, x)) x = y; return x;}
    template<typename Compare, typename T>
    inline T& UP(T& x, const T& y, Compare comp){if(comp(y, x)) x = y; return x;}

    template<typename T> inline T& GT(T& x, const T& y){return UP<std::greater>(x, y);}
    template<typename T> inline T& LS(T& x, const T& y){return UP<std::less>(x, y);}

    template<typename T>
    struct Mapper
    {
        int operator[](const T& v) { int& ret = table[v]; if(!ret) rtable[ret = table.size()] = v; return ret - 1; }
        template<typename... Args> int operator()(Args... args) { return (*this)[T(args...)]; }
        T rev(int idx){return rtable[idx + 1];}
        std::map<T, int> table;
        std::map<int, T> rtable;
    };

    template<typename T, int S>
    struct ReferenceArray
    {
        struct It {typename std::array<T*, S>::iterator it; T& operator*(){return **it;} void operator++(){it++;} bool operator!=(const It& other){return it != other.it;} };
        int size()const{return _ptr.size();}
        It begin()const{return {_ptr.begin()};}
        It end()const{return {_ptr.end()};}
        T& operator[](int idx)const{return *_ptr[idx];}
        mutable std::array<T*, S> _ptr;
    };
    template<typename T, typename... Args> 
    ReferenceArray<T, sizeof...(Args) + 1> MAKEV(T& arg1, Args&... args) {return {&arg1, &args...};}

    struct Range
    {   
        struct It {   int num, step; int operator*(){return num;} void operator++(){num += step;} bool operator!=(const It& other){return num != other.num;} };
        Range(int ee):b(0),e(ee){}
        Range(int bb, int ee):b(bb), e(ee){}
        It begin(){return {b, (b < e? 1: -1)};}
        It end(){return {e, 0};}
        int b, e;
    };

}




template<unsigned int P>
struct ZpZ
{
    using U64 = unsigned long long int;
    U64 value;
    ZpZ(long long int n) {if(std::abs(n) >= P)n %= P; if(n < 0)n += P; value = n;}
    ZpZ():value(0){}
    ZpZ& operator+=(ZpZ p){if((value += p.value) >= P)value -= P; return *this;}
    ZpZ& operator-=(ZpZ p){if(value >= p.value)value -= p.value; else value += P - p.value; return *this;}
    ZpZ& operator*=(ZpZ p){value = value * p.value % P; return *this;}
    ZpZ& operator/=(ZpZ p){value = value * p.inverse().value % P; return *this;}
    bool operator==(ZpZ p){return value == p.value;}
    bool operator!=(ZpZ p){return value != p.value;}

#define DEF(op) ZpZ operator op(ZpZ r)const{return ZpZ(value) op##= r;}
DEF(+)DEF(-)DEF(*)DEF(/)
#undef DEF

    explicit operator long long int(){return value;}
    explicit operator int(){return value;}
    ZpZ operator-(){return P - value;}
    ZpZ inverse()
    {
        int a = value, b = P, u = 1, v = 0;
        while(b) 
        {
            int t = a / b;
            std::swap(a -= t * b, b); 
            std::swap(u -= t * v, v);
        }
        if(u < 0) u += P;
        return u;
    }
    ZpZ pow(U64 e)
    {
        U64 ret = 1, base = value;
        while(e)
        {
            if((e & 1) && ((ret *= base) >> 32))
                ret %= P;
            if((base *= base) >> 32)
                base %= P;
            e >>= 1;
        }
        return ret;
    }

};






#ifdef _MSC_VER
#include <intrin.h>
inline int CLZ(int n){unsigned long ret; _BitScanForward(&ret, n); return ret;}
//inline int CLZ(long long int n){unsigned long ret; _BitScanForward64(&ret, n); return ret;}
inline int CTZ(int n){unsigned long ret; _BitScanReverse( &ret, n); return 31 - ret;} 
//inline int CTZ(long long int n){unsigned long ret; _BitScanReverse64( &ret, n); return 63 - ret;} 
inline int POPCNT(int n){return __popcnt(n);}
//inline int POPCNT(long long int n){return __popcnt64(n);}
#endif

#ifdef __GNUC__
inline int CLZ(int n){return __builtin_clz(n);}
inline int CLZLL(long long int n){return __builtin_clzll(n);}
inline int CTZ(int n){return __builtin_ctz(n);}
inline int CTZLL(long long int n){return __builtin_ctzll(n);}
inline int POPCNT(int n){return __builtin_popcount(n);}
inline int POPCNTLL(long long int n){return __builtin_popcountll(n);}
#endif





template<typename T> struct ScanfSpecifier{};
#define DEF(T,V) template<> struct ScanfSpecifier<T>{static constexpr const char* value = V;};
DEF(int,"%d")DEF(double,"%lf")DEF(float,"%f")DEF(char,"%c")DEF(const char*,"%s")DEF(unsigned long,"%lu")DEF(char*,"%s")DEF(unsigned int, "%u")
#ifdef _MSC_VER
DEF(long long int,"%I64d")
#else
DEF(long long int,"%lld")
#endif
#undef DEF
template<typename T> int RD(T& arg){return std::scanf(ScanfSpecifier<T>::value, &arg);}
template<int S> int RD(char (&arg)[S]){return std::scanf("%s", arg);}
template<> int RD<char*>(char*& arg){return std::scanf("%s", arg);}
template<> int RD<char>(char& arg){return std::scanf(" %c", &arg);}
template<typename T, typename... Args> int RD(T& arg1, Args&... args) {return RD(arg1) + RD(args...);}
template<typename T> T RD(){T ret; RD(ret); return ret;}
template<typename It> void RDV(It begin, It end) { while(begin != end) RD(*begin++); }
template<typename C> void RDV(C& c) {RDV(std::begin(c), std::end(c));}
template<typename... Args> void WT(Args... args) { int alc = 0; int dummy[] = {((alc++? std::printf(" "): 0), std::printf(ScanfSpecifier<Args>::value, args), 0)...}; }
template<typename... Args> void WTL(Args... args) { WT(args...); std::printf("\n"); }
template<typename It> void WTV(It begin, It end) { int alc = 0; while(begin != end) (alc++? std::printf(" "): 0), WT(*begin++); }
template<typename C> void WTV(const C& c) {WTV(std::begin(c), std::end(c));}
template<typename It> void WTVL(It begin, It end) { WTV(begin, end); std::printf("\n"); }
template<typename C> void WTVL(const C& c) {WTVL(std::begin(c), std::end(c));}




//alias
//bit operation => CLZ,CTZ,POPCNT
const int MOD = 1e9 + 7;
using ZZ = ZpZ<MOD>;
ZZ min(ZZ a, ZZ b){return std::min(a.value, b.value);}
ZZ max(ZZ a, ZZ b){return std::max(a.value, b.value);}
//RD[L],RDV[L],WT[L],WTV[L] for i/o
template<typename T> T& UMAX(T& x, T y){return XX::UP<std::greater>(x, y);}
template<typename T> T& UMIN(T& x, T y){return XX::UP<std::less>(x, y);}
using XX::UP; //(x,y) comp
using RG = XX::Range;
using XX::MAKEV;
using XX::Mapper;
//template
#include <vector>
#include <string>
#include <set>
#include <map>
#include <cstdlib>
#include <algorithm>
#include <functional>
using namespace std;


int N, X, Y, Z;
int W[4];
int len;

ZZ dp[41][1 << 18];


int next_s[1 << 18][11];


void pre()
{
    for(int z = (1 << len) - 1; z > 0; z--)
        for(int d = 1; d <= 10; d++)
        {
            int res = 1;

            for(int i = 0, l2 = 0; i < 3; l2 += W[i++])
                for(int l = 0; l < W[i]; l++)
                    if((z & (1 << (l2 + l))) && l + d <= W[i])
                        res |= 1 << (l2 + l + d);

            next_s[z][d] = res;
        }
}

ZZ f(int l, int mask)
{
    if(l < 0)
        return 0;

    auto& ret = dp[l][mask];

    if((int)ret)
        return ret - 1;

    if((mask >> len) & 1)
        ret = ZZ(10).pow(l);
    else
    {
        for(int d = 1; d <= 10; d++)
        {
            ret += f(l - 1, next_s[mask][d]);
//            WTL("#", mask, d, next_s[mask][d], l, (int)f(l - 1, next_s[mask][d]));
        }
    }

    ret += 1;

    return ret - 1;
}


int main()
{
    RD(N, W[0], W[1], W[2]);

    len = W[0] + W[1] + W[2];
    pre();
    
    WTL((int)f(N, 1));
}





Measured memory_bytes: 89728