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)

//by yjz
#include<bits/stdc++.h>
using namespace std;
#define FF first
#define SS second
#define PB push_back
#define MP make_pair
#define foreach(it,s) for(__typeof((s).begin()) it=(s).begin();it!=(s).end();it++)
#ifndef LOCAL
#define cerr if(0)cout
#endif
typedef long long ll;
const int mod = 1e9+7;
//My i/o stream
struct fastio
{
	char s[100000];
	int it, len;
	fastio() {it=len=0;}
	inline char get()
	{
		if (it<len) return s[it++]; it=0;
		len=fread(s, 1, 100000, stdin);
		if (len==0) return EOF; else return s[it++];
	}
	bool notend()
	{
		char c=get();
		while (c==' '||c=='\n') c=get();
		if (it>0) it--;
		return c!=EOF;
	}
}_buff;
#define geti(x) x=getnum()
#define getii(x,y) geti(x),geti(y)
#define getiii(x,y,z) getii(x,y),geti(z)
#define puti(x) putnum(x),putchar(' ')
#define putii(x,y) puti(x),puti(y)
#define putiii(x,y,z) putii(x,y),puti(z)
#define putsi(x) putnum(x),putchar('\n')
#define putsii(x,y) puti(x),putsi(y)
#define putsiii(x,y,z) putii(x,y),putsi(z)
inline ll getnum()
{
	ll r=0; bool ng=0; char c; c=_buff.get();
	while (c!='-'&&(c<'0'||c>'9')) c=_buff.get();
	if (c=='-') ng=1, c=_buff.get();
	while (c>='0'&&c<='9') r=r*10+c-'0', c=_buff.get();
	return ng?-r:r;
}
template <class T> inline void putnum(T x)
{
	if (x<0) putchar('-'), x=-x;
	register short a[20]={}, sz=0;
	while (x) a[sz++]=x%10, x/=10;
	if(sz==0) putchar('0');
	for (int i=sz-1; i>=0; i--) putchar('0'+a[i]);
}
inline char getreal() {char c=_buff.get(); while (c<=32) c=_buff.get(); return c;}
ll qpow(ll x, ll k) {return k==0? 1: 1ll*qpow(1ll*x*x%mod,k>>1)*(k&1?x:1)%mod;}
int n, m, l;
vector<int> v;
int getid(int x) {return lower_bound(v.begin(), v.end(), x)-v.begin();}
pair<int,int> rtr[15];
vector<int> con[33];
int id[33];
void dfs(int x, int g)
{
	id[x] = g;
	for (auto u : con[x])
	{
		if (id[u]==-1) dfs(u, g);
	}
}
int to_msk[1<<15];
ll cnt1[1<<15];
int w[33];
int calc_cost(int msk0, int msk1, int c)
{
	int ret = 1;
	if (v[0]==0)
	{
		if ((msk1&1)&&c!=0) return 0;
	}
	else
	{
		if (msk1&1)
		{
			if (c==0) ret = w[0]+1;
			else ret = w[0];
		}
	}
	for (int i=1; i<l; i++)
	{
		if (((msk1>>id[i])&1)&&((msk0>>id[i-1])&1))
		{
			ret = 1ll*ret*w[i]%mod;
		}
		else if (((msk0>>id[i])&1)&&((msk1>>id[i-1])&1))
		{
			ret = 1ll*ret*w[i]%mod;
		}
		else if (((msk1>>id[i])&1)&&((msk1>>id[i-1])&1))
		{
			ret = 1ll*ret*(w[i]+1)%mod;
		}
	}
	return ret;
}
void init()
{
	sort(v.begin(), v.end());
	v.erase(unique(v.begin(), v.end()), v.end());
	l = v.size();
	for (int i=0; i<m; i++)
	{
		int x = getid(rtr[i].FF), y = getid(rtr[i].SS);
///		cerr<<x<<"-"<<y<<endl;
		con[x].PB(y);
		con[y].PB(x);
	}
	memset(id, -1, sizeof(id));
	n = 0;
	for (int i=0; i<l; i++) if (id[i]==-1) dfs(i, n++);
	for (int i=0; i<l; i++)
	{
		int len = v[i]-(i==0?0:v[i-1]);
		w[i] = 1ll*(qpow(10, len)+mod-1)*qpow(9, mod-2)%mod;
	}
}
int dp[10][1<<15];
int main()
{
	int L;
	geti(L);
	geti(m);
	for (int i=0; i<m; i++)
	{
		int l, r;
		getii(l, r);
		l--;
		rtr[i] = MP(l, r);
		v.PB(l);
		v.PB(r);
	}
	init();
	assert(n<=15);
	dp[0][0] = 1;
	for (int j=0; j<(1<<n); j++)
	{
		int MSK = (1<<n)-1-j;
		int msk = MSK;
			for (int i=0; i<9; i++)
			{
				dp[i+1][j] = (dp[i+1][j]+dp[i][j])%mod;
//				cerr<<i<<","<<j<<" "<<dp[i][j]<<endl;
			}
		while (msk>0)
		{
			if (j==0)
			{
				dp[1][j|msk] = (dp[1][j|msk]+1ll*dp[0][j]*calc_cost(j, msk, 0))%mod;
			}
			int cost = calc_cost(j, msk, 1);
			for (int i=1; i<9; i++)
			{
				dp[i+1][j|msk] = (dp[i+1][j|msk]+1ll*dp[i][j]*cost)%mod;
			}
			msk = (msk-1)&MSK;
		}
	}
	int ans = 1ll*dp[9][(1<<n)-1]*qpow(10, L-v.back())%mod;
	cout<<(ans+mod)%mod<<endl;
	return 0;
}