/**/ #include using namespace std; /***********************************************/ /* Dear online judge: * I've read the problem, and tried to solve it. * Even if you don't accept my solution, you should respect my effort. * I hope my code compiles and gets accepted. * ___ __ _______ _______ * |\ \|\ \ |\ ___ \ |\ ___ \ * \ \ \/ /|_\ \ __/| \ \ __/| * \ \ ___ \\ \ \_|/__\ \ \_|/__ * \ \ \\ \ \\ \ \_|\ \\ \ \_|\ \ * \ \__\\ \__\\ \_______\\ \_______\ * \|__| \|__| \|_______| \|_______| */ const long long mod = 1000000007; long long fact[100100],inv[100100],p2[100100]; long long pow_mod(long long base,long long power) { long long res = 1ll; while(power) { if(power&1) res = res * base % mod; base = base * base % mod; power >>= 1; } return res; } long long NCR(long long N,long long R) { if(R > N) return 0; return (fact[N] * inv[R] % mod) * inv[N-R] % mod; } struct node { int cnt[26]; node() { memset(cnt,0,sizeof cnt); } }; string s; int N; node tree[400010]; int lz[400010]; node merge(node a,node b) { node res = node(); for(int i = 0;i < 26;i++) { res.cnt[i] = a.cnt[i] + b.cnt[i]; } return res; } void push(int n,int l,int r) { if(l == r || !lz[n]) { return; } node prel = tree[2*n+1],prer = tree[2*n+2]; for(int i = 0;i < 26;i++) { tree[2*n+1].cnt[(i+lz[n])%26] = prel.cnt[i]; tree[2*n+2].cnt[(i+lz[n])%26] = prer.cnt[i]; } lz[2*n+1] = (lz[2*n+1] + lz[n])%26; lz[2*n+2] = (lz[2*n+2] + lz[n])%26; lz[n] = 0; } void build(int n = 0,int l = 0,int r = N - 1) { if(l == r) { tree[n].cnt[s[l] - 'a']++; return; } int md = (l+r)>>1; build(2*n+1,l,md); build(2*n+2,md+1,r); tree[n] = merge(tree[2*n+1],tree[2*n+2]); } node get(int a,int b,int n = 0,int l = 0,int r = N - 1) { push(n,l,r); if(l == a && r == b) { return tree[n]; } int md = (l+r)>>1; node res = node(); if(a <= md) res = get(a,min(b,md),2*n+1,l,md); if(b > md) res = merge(res,get(max(a,md+1),b,2*n+2,md+1,r)); return res; } int val; void upd(int a,int b,int n = 0,int l = 0,int r = N - 1) { push(n,l,r); if(l == a && b == r) { node pre = tree[n]; for(int i = 0;i < 26;i++) { tree[n].cnt[(i+val)%26] = pre.cnt[i]; } lz[n] = val; return; } int md = (l+r)>>1; if(a <= md) upd(a,min(b,md),2*n+1,l,md); if(b > md) upd(max(a,md+1),b,2*n+2,md+1,r); tree[n] = merge(tree[2*n+1],tree[2*n+2]); return; } long long dp[26][2]; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); fact[0] = fact[1] = inv[0] = inv[1] = 1; p2[0] = 1,p2[1] = 2; for(int i = 2;i < 100100;i++) fact[i] = fact[i-1] * i % mod,p2[i] = 2 * p2[i-1] % mod; inv[100099] = pow_mod(fact[100099],mod-2); for(int i = 100098;i >= 2;i--) inv[i] = inv[i+1] * (i+1) % mod; int Q,l,r,t; cin>>N>>Q; cin>>s; build(); while(Q--) { cin>>t>>l>>r; if(t==1) { cin>>val; upd(l,r); continue; } node seg = get(l,r); for(int i = 0;i < 26;i++) { if(!i) { if(seg.cnt[i] == 0) { dp[i][0] = 1; dp[i][1] = 0; }else { dp[i][0] = dp[i][1] = p2[seg.cnt[i]-1]; } }else { if(seg.cnt[i] == 0) { dp[i][0] = dp[i-1][0]; dp[i][1] = dp[i-1][1]; }else { dp[i][0] = dp[i-1][0] * p2[seg.cnt[i]-1] % mod; dp[i][1] = (dp[i-1][1] + dp[i-1][0]) * p2[seg.cnt[i] - 1]%mod; } } } cout<<(dp[25][0] + dp[25][1] + mod - 1)%mod<<'\n'; } return 0; } /**/