1 #include<cstdio>
2 #include<cstring>
3 #include<cmath>
4 #include<ctime>
5 #include<iostream>
6 #include<algorithm>
7 #include<queue>
8 #include<set>
9 #define inf (0x7fffffff)
10 #define l(a) ((a)<<1)
11 #define r(a) ((a)<<1|1)
12 #define b(a) (1<<(a))
13 #define rep(i,a,b) for(int i=a;i<=(b);i++)
14 #define clr(a) memset(a,0,sizeof(a))
15 typedef long long ll;
16 typedef unsigned long long ull;
17 using namespace std;
18 int readint(){
19 int t=0,f=1;char c=getchar();
20 while(!isdigit(c)){
21 if(c=='-') f=-1;
22 c=getchar();
23 }
24 while(isdigit(c)){
25 t=(t<<3)+(t<<1)+c-'0';
26 c=getchar();
27 }
28 return t*f;
29 }
30 const int maxn=100009;
31 struct node{
32 int l,r;
33 ll s,a,m;
34 }x[maxn<<2];
35 int n,m;
36 ll mod;
37 void maintain(int t){
38 x[t].s=(x[l(t)].s+x[r(t)].s)%mod;
39 }
40 void pushdown(int t){
41 if(x[t].l==x[t].r){
42 x[t].a=0;x[t].m=1;return;
43 }
44 if(x[t].m!=1){
45 x[l(t)].s=x[l(t)].s*x[t].m%mod;
46 x[r(t)].s=x[r(t)].s*x[t].m%mod;
47 x[l(t)].m=x[l(t)].m*x[t].m%mod;x[r(t)].m=x[r(t)].m*x[t].m%mod;
48 x[l(t)].a=x[l(t)].a*x[t].m%mod;x[r(t)].a=x[r(t)].a*x[t].m%mod;
49 x[t].m=1;
50 }
51 if(x[t].a){
52 x[l(t)].s=(x[l(t)].s+(x[l(t)].r-x[l(t)].l+1)*x[t].a)%mod;
53 x[r(t)].s=(x[r(t)].s+(x[r(t)].r-x[r(t)].l+1)*x[t].a)%mod;
54 x[l(t)].a=(x[l(t)].a+x[t].a)%mod;x[r(t)].a=(x[r(t)].a+x[t].a)%mod;
55 x[t].a=0;
56 }
57 }
58 ll del;
59 void add(int t,int l,int r){
60 pushdown(t);
61 if(x[t].l==l&&x[t].r==r){
62 x[t].s=(x[t].s+(x[t].r-x[t].l+1)*del)%mod;
63 x[t].a=(x[t].a+del)%mod;
64 return;
65 }
66 int mid=(x[t].l+x[t].r)>>1;
67 if(l>mid) add(r(t),l,r);
68 else if(r<=mid) add(l(t),l,r);
69 else{
70 add(l(t),l,mid);
71 add(r(t),mid+1,r);
72 }
73 maintain(t);
74 }
75 void mul(int t,int l,int r){
76 pushdown(t);
77 if(x[t].l==l&&x[t].r==r){
78 x[t].s=(x[t].s*del)%mod;
79 x[t].m=x[t].m*del%mod;
80 x[t].a=x[t].a*del%mod;
81 return;
82 }
83 int mid=(x[t].l+x[t].r)>>1;
84 if(l>mid) mul(r(t),l,r);
85 else if(r<=mid) mul(l(t),l,r);
86 else{
87 mul(l(t),l,mid);
88 mul(r(t),mid+1,r);
89 }
90 maintain(t);
91 }
92 ll qury(int t,int l,int r){
93 pushdown(t);
94 if(x[t].l==l&&x[t].r==r) return x[t].s;
95 int mid=(x[t].l+x[t].r)>>1;
96 if(l>mid) return qury(r(t),l,r)%mod;
97 if(r<=mid) return qury(l(t),l,r)%mod;
98 return (qury(l(t),l,mid)%mod+qury(r(t),mid+1,r)%mod)%mod;
99 }
100 void build(int t,int l,int r){
101 x[t].l=l;x[t].r=r;x[t].m=1;
102 if(l==r){
103 x[t].s=readint()%mod;
104 return;
105 }
106 int mid=(l+r)>>1;
107 build(l(t),l,mid);
108 build(r(t),mid+1,r);
109 maintain(t);
110 }
111 int main(){
112 //freopen("#input.txt","r",stdin);
113 //freopen("#output.txt","w",stdout);
114 n=readint();m=readint();mod=readint();
115 build(1,1,n);
116 while(m--){
117 int opt=readint(),L=readint(),R=readint();
118 if(opt==3) printf("%lld\n",(qury(1,L,R)+mod)%mod);
119 else{
120 del=readint()%mod;
121 if(opt==2) add(1,L,R);
122 else mul(1,L,R);
123 }
124 }
125 //fclose(stdin);
126 //fclose(stdout);
127 return 0;
128 }