#include using namespace std; #define inf (1<<30)-1 #define INF (1LL<<62)-1 #define MOD 1000000007LL #define MP make_pair #define PB push_back #define ALL(x) x.begin(),x.end() #define PI acos(-1) #define MEM(x,y) memset(x,y,sizeof (x)) #define debug cout<<"A"<<'\n' #define REP(i,a,b) for (int i=(a); i<=(b); i++) #define PER(i,a,b) for (int i=(a); i>=(b); i--) #define REPL(i,a,b) for (LL i=(a); i<=(b); i++) #define PERL(i,a,b) for (LL i=(a); i>=(b); i--) #define print(x) cout<PII; typedef pairPLL; typedef set SI; typedef set SL; typedef set SS; typedef vector VI; typedef vector VL; typedef vector VS; typedef map MII; typedef map MLL; typedef queue QI; /* Direction Array */ // int fx[]={1,-1,0,0}; // int fy[]={0,0,1,-1}; // int fx[]={0,0,1,-1,-1,1,-1,1}; // int fy[]={-1,1,0,0,1,1,-1,-1}; template inline T bigmod(T p,T e,T M) { T ret = 1; for(; e > 0; e >>= 1) { if(e & 1) ret = (ret * p) % M; p = (p * p) % M; } return (T)ret; } template inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);} template inline T modinverse(T a,T M){return bigmod(a,M-2,M);} template inline T lcm(T a,T b) {a=abs(a);b=abs(b); return (a/gcd(a,b))*b;} template inline bool getbit(T a, X i) { T t=1; return ((a&(t<0);} template inline T setbit(T a, X i) { T t=1;return (a|(t< inline T resetbit(T a, X i) { T t=1;return (a&(~(t<=0)?a:-a;} /*end of header*/ int n,q; string s; struct data { int arr[26]; }; data tree[300001]; int prop[300001]; void make(int node,int b,int e) { if(b==e) { MEM(tree[node].arr,0); tree[node].arr[s[b]-'a']=1; return; } int mid=(b+e)/2; make(2*node,b,mid);make(2*node+1,mid+1,e); REP(i,0,25)tree[node].arr[i]=tree[2*node].arr[i]+tree[2*node+1].arr[i]; } void update(int node,int b,int e,int I,int J,int val) { if(b>J || e=I && e<=J) { data d; MEM(d.arr,0); REP(i,0,25)d.arr[(i+val)%26]+=tree[node].arr[i]; REP(i,0,25)tree[node].arr[i]=d.arr[i]; prop[node]+=val; prop[node]%=26; return; } int left=2*node,right=2*node+1,mid=(b+e)/2; update(left,b,mid,I,J,val); update(right,mid+1,e,I,J,val); REP(i,0,25)tree[node].arr[i]=tree[2*node].arr[i]+tree[2*node+1].arr[i]; data d; MEM(d.arr,0); REP(i,0,25)d.arr[(i+prop[node])%26]+=tree[node].arr[i]; REP(i,0,25)tree[node].arr[i]=d.arr[i]; return; } data query(int node, int b,int e,int I,int J,int carry) { if(b>J || e=I && e<=J) { data d; MEM(d.arr,0); REP(i,0,25)d.arr[(i+carry)%26]+=tree[node].arr[i]; return d; } int left=2*node,right=2*node+1,mid=(b+e)/2; data p1,p2; p1=query(left,b,mid,I,J,(carry+prop[node])%26); p2=query(right,mid+1,e,I,J,(carry+prop[node])%26); data d; REP(i,0,25)d.arr[i]=p1.arr[i]+p2.arr[i]; return d; } int main() { //freopen("input_file_name.in","r",stdin); //freopen("output_file_name.out","w",stdout); scanf("%d %d",&n,&q); cin>>s; int type,st,en,t; MEM(prop,0); make(1,0,n-1); while(q--) { scanf("%d",&type); if(type==1) { scanf("%d %d %d",&st,&en,&t); t%=26; update(1,0,n-1,st,en,t); } else { scanf("%d %d",&st,&en); data d=query(1,0,n-1,st,en,0); LL guun=1,temp=0,ans,temp1=0; REP(i,0,25) { temp+=d.arr[i]/2; temp1+=(d.arr[i]!=0); } ans=bigmod(2LL,temp,MOD); ans*=(temp1+1); ans%=MOD; ans--; ans+=MOD; ans%=MOD; printf("%lld\n",ans); } } return 0; }