#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
const int MAXP = 131072;
const int MOD = 1e9 + 7;
const int MAXC = 9;
struct segTree {
//primul este ca sa stiu daca 0 - nu incepe cu 3, 1 - incepe cu 3
//al doilea este ca sa stiu daca 0 - nu se termina cu 1, 1 - se termina cu 1
int countEq[2][2], countLess[2][2], countAll[2][2];//countAll ar fi putut sa fie precalculat
} v[2 * MAXP];
void buildCif(int nod, int cif) {
int a, b, x, rez2;
for (a = 0; a < 2; a++) {
for (b = 0; b < 2; b++) {
v[nod].countEq[a][b] = v[nod].countAll[a][b] = v[nod].countLess[a][b] = 0;//mai intai le resetez ca poate am avut alta cifra pana acum aici
for (x = 0; x <= MAXC; x++) {
rez2 = 0;
if (a == (x == 3) && b == (x == 1)) {
rez2 = 1;
}
if (x < cif) {
v[nod].countLess[a][b] += rez2;
}
v[nod].countAll[a][b] += rez2;
}
}
}
v[nod].countEq[(cif == 3)][(cif == 1)] = 1;
}
segTree join(segTree st, segTree dr) {
segTree rez;
int a, b, c, d;
for (a = 0; a < 2; a++) {
for (d = 0; d < 2; d++) {
rez.countAll[a][d] = rez.countEq[a][d] = rez.countLess[a][d] = 0;//il initializez cu 0
}
}
for (b = 0; b < 2; b++) {
for (c = 0; c < 2; c++) {
if (b + c < 2) {//daca sunt amandoi 1 inseamna ca se formeaza un 13 si nu ar trebui
for (a = 0; a < 2; a++) {
for (d = 0; d < 2; d++) {
rez.countAll[a][d] = (rez.countAll[a][d] + (long long)st.countAll[a][b] * dr.countAll[c][d]) % MOD;
rez.countEq[a][d] = (rez.countEq[a][d] + (long long)st.countEq[a][b] * dr.countEq[c][d]) % MOD;
rez.countLess[a][d] = (rez.countLess[a][d] + (long long)st.countLess[a][b] * dr.countAll[c][d] + (long long)st.countEq[a][b] * dr.countLess[c][d]) % MOD;
}
}
}
}
}
return rez;
}
void build(int nod, int st, int dr) {
int mid;
char ch;
if (st == dr) {
ch = fgetc(stdin) - '0';
buildCif(nod, ch);
} else {
mid = (st + dr) / 2;
build(2 * nod, st, mid);
build(2 * nod + 1, mid + 1, dr);
v[nod] = join(v[2 * nod], v[2 * nod + 1]);
}
}
void update(int nod, int st, int dr, int poz, int val) {
int mid;
if (st == dr) {
buildCif(nod, val);
} else {
mid = (st + dr) / 2;
if (poz <= mid) {
update(2 * nod, st, mid, poz, val);
} else {
update(2 * nod + 1, mid + 1, dr, poz, val);
}
v[nod] = join(v[2 * nod], v[2 * nod + 1]);
}
}
segTree query(int nod, int st, int dr, int x, int y) {
int mid, nr1, nr2;
segTree rez1, rez2;
if (x <= st && y >= dr) {
return v[nod];
} else {
mid = (st + dr) / 2;
nr1 = nr2 = 0;
if (x <= mid) {
rez1 = query(2 * nod, st, mid, x, y);
nr1 = 1;
}
if (y > mid) {
rez2 = query(2 * nod + 1, mid + 1, dr, x, y);
nr2 = 1;
}
if (nr1 + nr2 == 2) {
return join(rez1, rez2);
} else if (nr1 == 1) {
return rez1;
} else {
return rez2;
}
}
}
int calcRez(segTree rez) {
int nr, a, d;
nr = 0;
for (a = 0; a < 2; a++) {
for (d = 0; d < 2; d++) {
nr = (nr + rez.countLess[a][d] + rez.countEq[a][d]) % MOD;//nu pun long long ca countEq este 0 sau 1
}
}
return nr;
}
int main()
{
//aint in O(n + q * log(n)) cu constanta aproape 16 = 2^4 cred
int n, q, i, cer, x, y;
segTree rez;
scanf("%d%d ", &n, &q);
build(1, 1, n);
printf("%d\n", calcRez(query(1, 1, n, 1, n)));
for (i = 0; i < q; i++) {
scanf("%d%d%d", &cer, &x, &y);
if (cer == 1) {
rez = query(1, 1, n, x, y);
printf("%d\n", calcRez(rez));
} else {
update(1, 1, n, x, y);
}
}
return 0;
}