//#pragma comment(linker,"/STACK:16777216") /*16Mb*/ #pragma comment(linker,"/STACK:33554432") /*32Mb*/ #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS #endif #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define FOR(i,a,b) for (int i = (a); i < (b); i++) #define RFOR(i,b,a) for (int i = (b)-1; i >= (a); i--) #define ITER(it,a) for (__typeof(a.begin()) it = a.begin(); it != a.end(); it++) #define FILL(a,value) memset(a, value, sizeof(a)) #define SZ(a) (int)a.size() #define ALL(a) a.begin(), a.end() #define MP make_pair #define PB push_back typedef long long LL; typedef vector VI; typedef pair PII; const double PI = acos(-1.0); const int INF = 1000 * 1000 * 1000 + 7; const LL LINF = INF * (LL) INF; const int MAX = 131072; int n, q; int tp, l, r; string s; int num[100007][30]; int val[30], temp[30]; struct Tree { int a[2*MAX][30]; int cycl[2*MAX]; void init() { FOR (i,0,n) FOR (j,0,'z'-'a'+1) a[MAX+i][j] = num[i][j]; RFOR (i,MAX,0) FOR (j,0,'z'-'a'+1) a[i][j] = a[2*i][j] + a[2*i+1][j]; } void Ppush(int pos) { if (pos < MAX) { cycl[2*pos] += cycl[pos], cycl[2*pos+1] += cycl[pos]; cycl[2*pos] %= ('z'-'a'+1); cycl[2*pos+1] %= ('z'-'a'+1); } FOR (i,0,'z'-'a'+1) temp[i] = a[pos][i]; FOR (i,0,'z'-'a'+1) a[pos][(i+cycl[pos])%('z'-'a'+1)] = temp[i]; cycl[pos] = 0; } void push(int pos) { pos /= 2; while (pos) { Ppush(2*pos); Ppush(2*pos+1); FOR (j,0,'z'-'a'+1) a[pos][j] = a[2*pos][j] + a[2*pos+1][j]; pos /= 2; } } void add(int l, int r, int val) { l += MAX; r += MAX; val %= ('z'-'a'+1); while (l <= r) { if (l&1) { cycl[l] = (cycl[l]+val)%('z'-'a'+1); push(l); l++; } if ((r&1) == 0) { cycl[r] = (cycl[r]+val)%('z'-'a'+1); push(r); r--; } l/=2; r/=2; } } void get(int l, int r) { l += MAX; r += MAX; while (l <= r) { if (l&1) { int L = l; int sh = 0; while (L) { sh += cycl[L]; L /= 2; } FOR (j,0,'z'-'a'+1) val[(j+sh)%('z'-'a'+1)] += a[l][j]; l++; } if ((r&1) == 0) { int R = r; int sh = 0; while (R) { sh += cycl[R]; R /= 2; } FOR (j,0,'z'-'a'+1) val[(j+sh)%('z'-'a'+1)] += a[r][j]; r--; } l/=2; r/=2; } } } T; LL mpow(LL step, LL a = 2) { LL res = 1; while (step) { if (step & 1) { res = (res*a)%INF; } a = (a*a)%INF; step /= 2; } return res; } int main() { //freopen("in.txt", "r", stdin); //ios::sync_with_stdio(false); cin.tie(0); cin >> n >> q; cin >> s; FOR (i,0,s.size()) { //if (i) // FOR (j,0,'z'-'a'+1) num[i][j] = num[i-1][j]; num[i][s[i]-'a']++; }; T.init(); FOR (qwe,0,q) { cin >> tp; if (tp == 2) { cin >> l >> r; FOR (i,0,'z'-'a'+1) val[i] = 0; T.get(l,r); //FOR (i,0,'z'-'a'+1) val[i] = num[r][i]; //if (l >= 1) FOR (i,0,'z'-'a'+1) val[i] -= num[l-1][i]; //FOR (i,0,3) cout << val[i]<<" "; //cout << endl; LL res = 1, ans = 0, Q = 0; FOR (i,0,'z'-'a'+1) if (val[i]) { res *= mpow(val[i]-1); res %= INF; Q++; } ans = (res-1 + Q*res)%INF; cout << ans << "\n"; } else { int val; cin >> l >> r >> val; T.add(l,r,val); } } return 0; }