#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<string>
#include<cstring>
#include<set>
#include<vector>
#include<utility>
#include<stack>
#include<list>
#include<queue>
#include<climits>
#include<tuple>
using namespace std;
#define int long long
#define pii pair<int,int>
#define l(x) x&(-x)
int n,m,sferdd;
#define mod sferdd
int ai[100010];
struct tree{
int sum,l,r,add,minus;
}p[800010];
void push_up(int t){
p[t].sum=(p[2*t].sum+p[2*t+1].sum)%mod;
}
void push_down(int t){
int rch=2*t+1,lch=2*t,add=p[t].add,mnu=p[t].minus;
p[lch].sum=(p[lch].sum+add*(p[lch].r-p[lch].l+1))%mod*(!mnu?1:mnu*(p[lch].r-p[lch].l+1))%mod;
p[rch].sum=(p[rch].sum+add*(p[rch].r-p[rch].l+1))%mod*(!mnu?1:mnu*(p[rch].r-p[rch].l+1))%mod;
p[lch].add+=add,p[rch].add+=add;
if(p[lch].minus)p[lch].minus=p[lch].minus*mnu%mod;else p[lch].minus=mnu%mod;
if(p[rch].minus)p[rch].minus=p[rch].minus*mnu%mod;else p[rch].minus=mnu%mod;
p[t]={p[t].sum,p[t].l,p[t].r,0,0};
}
void build(int now,int l,int r){
if(l==r){p[now].sum=ai[l],p[now].l=l,p[now].r=r;return;}
int mid=(l+r)>>1;build(now*2,l,mid);build(now*2+1,mid+1,r);
push_up(now);p[now].l=l,p[now].r=r;
}
void update(int o,int now,int l,int r,int t){
if(p[now].l>=l&&r>=p[now].r){
push_down(now);
if(o==1)p[now].sum=(p[now].sum*t)%mod,p[now].minus=t;
else p[now].sum=(p[now].sum+t)%mod,p[now].add=t;
return;
}
push_down(now);
int mid=(p[now].l+p[now].r)>>1;if(l<=mid)update(o,2*now,l,r,t);if(r>mid)update(o,2*now+1,l,r,t);
push_up(now);
}
int query(int now,int l,int r){
if(p[now].l>=l&&r>=p[now].r)return p[now].sum;
int ans=0;
push_down(now);
int mid=(p[now].l+p[now].r)>>1;if(l<=mid)ans=(ans+query(2*now,l,r))%mod;if(r>mid)ans=(ans+query(2*now+1,l,r))%mod;
return ans%mod;
}
signed main(){
cin>>n>>m>>sferdd;
for(int x=1;x<=n;x++){
cin>>ai[x];
}build(1,1,n);
for(int x=1;x<=m;x++){
int o,a,b,c;
cin>>o>>a>>b;
if(o!=3){
cin>>c;
update(o,1,a,b,c);
}else cout<<query(1,a,b)<<endl;
}
return 0;
}