#include <bits/stdc++.h>
using namespace std;
int n, q;
vector<int> a;
bool read() {
  if (scanf("%d%d", &n, &q) < 2) {
    return 0;
  }
  a.resize(n);
  for (int i = 0; i < int(n); ++i) {
    scanf("%d", &a[i]);
  }
  return 1;
}
const int B = 10;
struct node {
  long long coef[B];
  int who[B];
  node() {
    memset(coef, 0, sizeof coef);
    reset_who();
  }
  node(long long x) : node() {
    long long pw = 1;
    while (x) {
      int dig = x % B;
      coef[dig] += pw;
      pw *= B;
      x /= B;
    }
  }
  void apply(int x, int y) {
    if (x == y) {
      return;
    }
    for (int i = 0; i < int(B); ++i) {
      if (who[i] == x) {
        who[i] = y;
      }
    }
  }
  void push(node& other) {
    static int dest[B];
    for (int i = 0; i < int(B); ++i) {
      dest[i] = who[other.who[i]];
    }
    memcpy(other.who, dest, sizeof dest);
  }
  void add(const node& other) {
    for (int i = 0; i < int(B); ++i) {
      coef[other.who[i]] += other.coef[i];
    }
  }
  long long sum() const {
    long long res = 0;
    for (int i = 0; i < int(B); ++i) {
      res += coef[i] * who[i];
    }
    return res;
  }
  void reset_who() {
    for (int i = 0; i < int(B); ++i) {
      who[i] = i;
    }
  }
  void reset_comps() {
    static long long ncoef[B];
    memset(ncoef, 0, sizeof ncoef);
    for (int i = 0; i < int(B); ++i) {
      ncoef[who[i]] += coef[i];
    }
    reset_who();
    memcpy(coef, ncoef, sizeof coef);
  }
  void print() const {
    for (int i = 0; i < int(B); ++i) {
      printf("%d: coef=%lld, who=%d\n", i, coef[i], who[i]);
    }
  }
};
struct SegmTree {
  vector<node> t;
  int sz;
  SegmTree() {}
  SegmTree(const vector<int>& a) {
    sz = 1;
    while (sz < ((int)(a).size())) sz *= 2;
    t.resize(sz * 2);
    for (int i = 0; i < int(((int)(a).size())); ++i) {
      t[sz + i] = node(a[i]);
    }
    for (int v = sz - 1; v > 0; --v) {
      recalc(v);
    }
  }
  void push(int v) {
    t[v].push(t[v * 2]);
    t[v].push(t[v * 2 + 1]);
    t[v].reset_comps();
  }
  void recalc(int v) {
    t[v] = node();
    t[v].add(t[v * 2]);
    t[v].add(t[v * 2 + 1]);
  }
  void change(int v, int tl, int tr, int l, int r, int x, int y) {
    l = max(l, tl);
    r = min(r, tr);
    if (l > r) {
      return;
    }
    if (l == tl && r == tr) {
      t[v].apply(x, y);
      return;
    }
    push(v);
    int tm = (tl + tr) >> 1;
    change(v * 2, tl, tm, l, r, x, y);
    change(v * 2 + 1, tm + 1, tr, l, r, x, y);
    recalc(v);
  }
  void change(int l, int r, int x, int y) { change(1, 0, sz - 1, l, r, x, y); }
  long long get(int v, int tl, int tr, int l, int r) {
    l = max(l, tl);
    r = min(r, tr);
    if (l > r) {
      return 0;
    }
    if (l == tl && r == tr) {
      return t[v].sum();
    }
    push(v);
    int tm = (tl + tr) >> 1;
    long long res = get(v * 2, tl, tm, l, r);
    res += get(v * 2 + 1, tm + 1, tr, l, r);
    recalc(v);
    return res;
  }
  long long get(int l, int r) { return get(1, 0, sz - 1, l, r); }
};
int do_replace(int num, int x, int y) {
  int nw = 0;
  int pw = 1;
  while (num) {
    int dig = num % 10;
    num /= 10;
    if (dig == x) {
      dig = y;
    }
    nw = pw * dig + nw;
    pw *= 10;
  }
  return nw;
}
namespace Brut {
vector<int> a;
long long get(int l, int r) {
  long long res = 0;
  for (int i = l; i <= r; ++i) {
    res += a[i];
  }
  return res;
}
void change(int l, int r, int x, int y) {
  for (int i = l; i <= r; ++i) {
    a[i] = do_replace(a[i], x, y);
  }
}
};  // namespace Brut
void solve() {
  SegmTree T(a);
  for (int it = 0; it < int(q); ++it) {
    int type;
    scanf("%d", &type);
    int l, r;
    scanf("%d%d", &l, &r);
    --l;
    --r;
    if (type == 1) {
      int x, y;
      scanf("%d%d", &x, &y);
      assert(y);
      T.change(l, r, x, y);
    } else if (type == 2) {
      printf("%lld\n", T.get(l, r));
    } else {
      assert(0);
    }
  }
}
int main() {
  while (read()) {
    solve();
  }
  return 0;
}
