Problem:
Score : 1400 points

Problem Statement

Count the number of strings S that satisfy the following constraints, modulo 10^9 + 7.

The length of S is exactly N.

S consists of digits (0...9).

You are given Q intervals.
For each i (1 \leq i \leq Q), the integer represented by S[l_i \ldots r_i] (the substring of S between the l_i-th (1-based) character and the r_i-th character, inclusive) must be a multiple of 9.

Here, the string S and its substrings may have leading zeroes.
For example, 002019 represents the integer 2019.

Constraints

1 \leq N \leq 10^9

1 \leq Q \leq 15

1 \leq l_i \leq r_i \leq N

Input

Input is given from Standard Input in the following format:

N
Q
l_1 r_1
:
l_Q r_Q

Output

Print the number of strings that satisfy the conditions, modulo 10^9 + 7.

Sample Input 1

4
2
1 2
2 4

Sample Output 1

136

For example, S = 9072 satisfies the conditions because both S[1 \ldots 2] = 90 and S[2 \ldots 4] = 072 represent multiples of 9.

Sample Input 2

6
3
2 5
3 5
1 3

Sample Output 2

2720

Sample Input 3

20
10
2 15
5 6
1 12
7 9
2 17
5 15
2 4
16 17
2 12
8 17

Sample Output 3

862268030

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include<bits/stdc++.h>

#define ll long long
#define fornum(A,B,C) for(A=B;A<C;A++)
#define mp make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>

using namespace std;

/////////////////////////////////////////////////////
#define MOD ((ll)1e9+7)

ll moddiv(ll a,ll b){
    a %= MOD;
    b %= MOD;
    for(ll m=MOD-2;m>0;m/=2){
        if(m&1){
            a=a*b%MOD;
        }
        b=b*b%MOD;
    }
    return a;
}

ll powl(ll a,ll b){
    if(b==0)
        return 1;
    return powl(a * a % MOD, b / 2) * (b & 1 ? a : 1) % MOD;
}
struct UnionFind{
    vector<int> nxt;
    UnionFind(int x){
        nxt.resize(x);
        for (int i = 0; i < x;i++){
            nxt[i] = i;
        }
    }
    int find(int x){
        if(nxt[x]==x)
            return x;
        return nxt[x] = find(nxt[x]);
    }
    inline void unite(int x,int y){
        nxt[find(y)] = find(x);
    }
};


ll N,Q;
ll l[33],r[33];
vector<ll> aiv[33];
vector<vector<ll>> dp;
vector<pll> av;
vector<ll> nv;
vector<ll> As;
ll i,j,k;
int main(){
    scanf("%lld%lld", &N,&Q);
    fornum(i,0,Q){
        scanf("%lld%lld",&l[i],&r[i]);
        --l[i];
        av.push_back({l[i], i});
        av.push_back({r[i], i});
    }
    
    sort(av.begin(), av.end());

    UnionFind uf(Q+1);
    aiv[av[0].second].push_back(0);
    fornum(i,1,av.size()){
        if(av[i].first != av[i - 1].first){
            As.push_back(moddiv(powl(10, av[i].first - av[i - 1].first) - 1 + MOD, 9));
        }else{
            uf.unite(av[i].second, av[i - 1].second);
        }
        aiv[av[i].second].push_back(As.size());
    }

    nv.assign(1 << Q, 1);
    fornum(i, 0, 1 << Q)
    {
        ll a = 0;
        fornum(j,0,Q){
            if(i&(1<<j)){
                fornum(k,0,2){
                    ll ii = aiv[j][k];
                    if(a&(1ll<<ii))
                        continue;
                    if(ii>0&&(a&(1ll<<(ii-1)))){
                        nv[i] = moddiv(nv[i] * (As[ii - 1] + 1), As[ii - 1]);
                    }
                    if(ii<As.size()&&(a&(1ll<<(ii+1)))){
                        nv[i] = moddiv(nv[i] * (As[ii] + 1), As[ii]);
                    }
                    a |= (1ll << ii);
                }
            }
        }
    }

    dp.assign(10, vector<ll>(1 << Q, 0));
    dp[0][0] = powl(10, av[0].first) * powl(10, N - av[av.size() - 1].first) % MOD;
    fornum(i,0,As.size()){
        dp[0][0] = dp[0][0] * As[i] % MOD;
    }
    fornum(i,0,9){
        fornum(j,0,(1<<Q)){
            fornum(k,0,Q){
                bool a = j & (1ll << k);
                bool b = j & (1ll << uf.find(k));
                if(a!=b)
                    break;
                if(i==0){
                    if(l[k]==av[0].first&&!a){
                        break;
                    }
                }
            }
            if(k<Q){
                continue;
            }
            
            dp[i + 1][j] += dp[i][j];
            for (k = j; k > 0;k=(k-1)&j){
                dp[i + 1][j] += dp[i][j ^ k] * nv[k];
                dp[i + 1][j] %= MOD;
            }
        }
    }

    printf("%lld", dp[9][(1 << Q) - 1]);
    return 0;
}