#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #pragma comment(linker, "/STACK:256000000") using namespace std; typedef long long int int64; typedef long double double80; const int INF = (1 << 29) + 5; const int64 LLINF = (1ll << 59) + 5; const int MOD = 1000 * 1000 * 1000 + 7; int n, q; char st[228228]; int cnt[28]; int64 dp_even[28]; int64 dp_odd[28]; int64 pw[228228]; int tree[450228][26]; int sh[450228]; void build(int v, int l, int r) { if (r - l == 1) { memset(tree[v], 0, sizeof(tree[v])); ++tree[v][st[l] - 'a']; } else { int m = (l + r) >> 1; build(2 * v + 1, l, m); build(2 * v + 2, m, r); for (int i = 0; i < 26; ++i) { tree[v][i] = tree[2 * v + 1][i] + tree[2 * v + 2][i]; } } } #define cp ggg int cp[28]; void upd(int v, int sh1) { sh[v] = (sh[v] + sh1) % 26; sh1 %= 26; for (int i = 0; i < 26; ++i) { cp[i] = tree[v][(i - sh1 + 26) % 26]; } for (int i = 0; i < 26; ++i) { tree[v][i] = cp[i]; } } void push(int v) { upd(2 * v + 1, sh[v]); upd(2 * v + 2, sh[v]); sh[v] = 0; } void upd_t(int v, int l, int r, int x, int y, int sh) { if (r <= x || y <= l) { return; } else if (x <= l && r <= y) { upd(v, sh); } else { push(v); int m = (l + r) >> 1; upd_t(2 * v + 1, l, m, x, y, sh); upd_t(2 * v + 2, m, r, x, y, sh); for (int i = 0; i < 26; ++i) { tree[v][i] = tree[2 * v + 1][i] + tree[2 * v + 2][i]; } } } void get(int v, int l, int r, int x, int y) { if (r <= x || y <= l) { return; } else if (x <= l && r <= y) { for (int i = 0; i < 26; ++i) { cnt[i] += tree[v][i]; } } else { push(v); int m = (l + r) >> 1; get(2 * v + 1, l, m, x, y); get(2 * v + 2, m, r, x, y); } } void get_dp() { int64 ans = 0; if (cnt[0] == 0) { dp_even[0] = 0; dp_odd[0] = 0; } else { dp_even[0] = ((pw[cnt[0] - 1] - 1) % MOD + MOD) % MOD; dp_odd[0] = pw[cnt[0] - 1]; } int64 cnt_even, cnt_odd; for (int i = 1; i < 26; ++i) { dp_even[i] = dp_even[i - 1]; dp_odd[i] = dp_odd[i - 1]; if (cnt[i] != 0) { cnt_even = ((pw[cnt[i] - 1] - 1) % MOD + MOD) % MOD; cnt_odd = pw[cnt[i] - 1]; dp_even[i] = (dp_even[i] + cnt_even * dp_even[i - 1] % MOD + cnt_even) % MOD; dp_odd[i] = (dp_odd[i] + dp_even[i - 1] * cnt_odd % MOD + cnt_odd + dp_odd[i - 1] * cnt_even % MOD) % MOD; } } printf("%lld\n", (dp_even[25] + dp_odd[25]) % MOD); } int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); scanf("%d%d", &n, &q); scanf("%s", &st); memset(sh, 0, sizeof(sh)); pw[0] = 1; for (int i = 1; i < 228228; ++i) { pw[i] = (pw[i - 1] * 2) % MOD; } build(0, 0, n); int type, l, r, sh1; for (int i = 0; i < q; ++i) { scanf("%d%d%d", &type, &l, &r); if (type == 1) { scanf("%d", &sh1); upd_t(0, 0, n, l, r + 1, sh1); } else { for (int j = 0; j < 26; ++j) { cnt[j] = 0; } get(0, 0, n, l, r + 1); get_dp(); } } fclose(stdin); fclose(stdout); return 0; }