import std.conv, std.functional, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.container, std.math, std.numeric, std.range, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }


// a^-1 (mod m)
long modInv(long a, long m)
// in {
  // assert(m > 0, "modInv: m > 0 must hold");
// }
// do {
{
  long b = m, x = 1, y = 0, t;
  for (; ; ) {
    t = a / b;
    a -= t * b;
    if (a == 0) {
      assert(b == 1 || b == -1, "modInv: gcd(a, m) != 1");
      if (b == -1) {
        y = -y;
      }
      return (y < 0) ? (y + m) : y;
    }
    x -= t * y;
    t = b / a;
    b -= t * a;
    if (b == 0) {
      assert(a == 1 || a == -1, "modInv: gcd(a, m) != 1");
      if (a == -1) {
        x = -x;
      }
      return (x < 0) ? (x + m) : x;
    }
    y -= t * x;
  }
}


int root(int[] uf, int u) {
  return (uf[u] < 0) ? u : (uf[u] = uf.root(uf[u]));
}
bool connect(int[] uf, int u, int v) {
  u = uf.root(u);
  v = uf.root(v);
  if (u == v) return false;
  if (uf[u] > uf[v]) swap(u, v);
  uf[u] += uf[v];
  uf[v] = u;
  return true;
}


enum MO = 10L^^9 + 7;

long ten(long n) {
  long a = 10, b = 1;
  for (; n; n >>= 1) {
    if (n & 1) {
      b = (b * a) % MO;
    }
    a = (a * a) % MO;
  }
  return b;
}

long ten9(long n) {
  long a = ten(n) - 1;
  for (; a % 9 != 0; a += MO) {}
  return a / 9;
}

long N;
int Q;
long[] L, R;

void main() {
  try {
    for (; ; ) {
      N = readLong();
      Q = readInt();
      L = new long[Q];
      R = new long[Q];
      foreach (q; 0 .. Q) {
        L[q] = readLong() - 1;
        R[q] = readLong();
      }
      
      auto uf = new int[Q];
      uf[] = -1;
      foreach (q0; 0 .. Q) foreach (q1; q0 + 1 .. Q) {
        if (L[q0] == L[q1] || L[q0] == R[q1] || R[q0] == L[q1] || R[q0] == R[q1]) {
          uf.connect(q0, q1);
        }
      }
      int m;
      auto ids = new int[Q];
      foreach (q; 0 .. Q) {
        if (uf[q] < 0) {
          ids[q] = m++;
        }
      }
      foreach (q; 0 .. Q) {
        ids[q] = ids[uf.root(q)];
      }
      
      Tuple!(long, int)[] xs;
      foreach (q; 0 .. Q) {
        xs ~= tuple(L[q], ids[q]);
        xs ~= tuple(R[q], ids[q]);
      }
      xs = xs.sort().uniq.array;
      const xsLen = cast(int)(xs.length);
      debug {
        writeln("m = ", m);
        writeln("xs = ", xs);
      }
      
      auto same = new long[][](m, m);
      foreach (i; 0 .. m) {
        same[i][] = 1;
      }
      foreach (h; 0 .. xsLen - 1) {
        const n = xs[h + 1][0] - xs[h][0];
        assert(n > 0);
        int i = xs[h][1], j = xs[h + 1][1];
        if (i > j) {
          swap(i, j);
        }
        (same[i][j] *= (((ten9(n) + 1) * modInv(ten9(n), MO)) % MO)) %= MO;
      }
      debug {
        writeln("same = ", same);
      }
      auto prod = new long[1 << m];
      foreach (p; 0 .. 1 << m) {
        prod[p] = 1;
        foreach (i; 0 .. m) foreach (j; i .. m) {
          if (((p >> i) & 1) && ((p >> j) & 1)) {
            (prod[p] *= same[i][j]) %= MO;
          }
        }
      }
      const head0 = ten9(xs[0][0]) + 1;
      const head1 = ten9(xs[0][0]);
      
      auto dp = new long[][](9 + 1, 1 << m);
      dp[0][0] = 1;
      foreach (z; 0 .. 9) {
        foreach (p; 0 .. 1 << m) {
          for (int r = p; ; --r &= p) {
            long tmp = (dp[z][p ^ r] * prod[r]) % MO;
            if ((r >> xs[0][1]) & 1) {
              (tmp *= ((z == 0) ? head0 : head1)) %= MO;
            }
            (dp[z + 1][p] += tmp) %= MO;
            if (!r) {
              break;
            }
          }
        }
      }
      debug {
        foreach (z; 0 .. 9 + 1) {
          writefln("dp[%s] = %s", z, dp[z]);
          writeln("  ", (dp[z][$ - 1] * 11) % MO);
        }
      }
      long ans = dp[9][$ - 1];
      foreach (h; 0 .. xsLen - 1) {
        const n = xs[h + 1][0] - xs[h][0];
        (ans *= ten9(n)) %= MO;
      }
      (ans *= ten(N - xs[xsLen - 1][0])) %= MO;
      writeln(ans);
    }
  } catch (EOFException e) {
  }
}
