1 #include<iostream>
2 #include<string>
3 #include<queue>
4 #include<stack>
5 #include<vector>
6 #include<map>
7 #include<cstdio>
8 #include<cstdlib>
9 #include<algorithm>
10 #include<set>
11 #include<iomanip>
12 #include<cstring>
13 #include<cmath>
14 #include<limits>
15 using namespace std;
16
17 #define au auto
18 #define debug(i) cout<<"debug: "<<i<<endl
19 #define mfor(i,a,b) for(register int i=(a);i<=(b);i++)
20 #define mrep(i,a,b) for(register int i=(a);i>=(b);i--)
21 #define LLL __int128
22 #define Re register
23 #define il inline
24 #define mem(a,b) memset(a,(b),sizeof(a))
25 typedef pair<int, int> intpair;
26 typedef long long int LL;
27 const int INF = 0x3f3f3f3f;
28 const long long int INFLL = 0x3f3f3f3f3f3f3f3f;
29
30 inline long long fpro(long long x, long long y, long long p)
31 {
32 long long z = (long double)x / p * y;
33 long long res = (unsigned long long)x * y - (unsigned long long)z * p;
34 return (res + p) % p;
35 }
36
37 int n, m;
38 int mod;
39 const int maxn = 200010;
40 int a[100010];
41
42 struct tree
43 {
44 int sum;
45 int l, r;
46 int atag;
47 int mtag;
48 tree()
49 {
50 mtag = 1;
51 atag = 0;
52 l = 0;
53 r = 0;
54 sum = 0;
55 }
56 }node[maxn << 2];
57
58 inline int lc(int x)
59 {
60 return x << 1;
61 }
62
63 inline int rc(int x)
64 {
65 return x << 1 | 1;
66 }
67
68 inline void push_up(int x)
69 {
70 node[x].sum = (node[lc(x)].sum + node[rc(x)].sum) % mod;
71 }
72
73 void build(int x, int l, int r)
74 {
75 node[x].l = l;
76 node[x].r = r;
77 if (l == r)
78 {
79 node[x].sum = a[l];
80 return;
81 }
82 int mid = (l + r) >> 1;
83 build(lc(x), l, mid);
84 build(rc(x), mid + 1, r);
85 push_up(x);
86 }
87
88 inline void push_down(int x)
89 {
90 node[lc(x)].sum = ((LL)node[x].mtag * node[lc(x)].sum + (node[lc(x)].r - node[lc(x)].l + 1) * (LL)node[x].atag) % mod;
91 node[rc(x)].sum = ((LL)node[x].mtag * node[rc(x)].sum + ((LL)node[rc(x)].r - node[rc(x)].l + 1) * node[x].atag) % mod;
92 node[lc(x)].mtag = (LL)node[x].mtag * node[lc(x)].mtag % mod;
93 node[rc(x)].mtag = (LL)node[x].mtag * node[rc(x)].mtag % mod;
94 node[lc(x)].atag = ((LL)node[x].mtag * node[lc(x)].atag + node[x].atag) % mod;
95 node[rc(x)].atag = ((LL)node[x].mtag * node[rc(x)].atag + node[x].atag) % mod;
96 node[x].mtag = 1;
97 node[x].atag = 0;
98 }
99
100 inline void update_add(int left, int right, int x, int k)
101 {
102 if (left <= node[x].l && node[x].r <= right)
103 {
104 (node[x].atag += k) %= mod;
105 (node[x].sum += (LL)(node[x].r - node[x].l + 1) * k) %= mod;
106 return;
107 }
108 push_down(x);
109 push_up(x);
110 int mid = (node[x].l + node[x].r) >> 1;
111 if (left <= mid) update_add(left, right, lc(x), k);
112 if (right > mid) update_add(left, right, rc(x), k);
113 push_up(x);
114 }
115
116 inline void update_mul(int left, int right, int x, int k)
117 {
118 if (left <= node[x].l && node[x].r <= right)
119 {
120 node[x].atag = (LL)node[x].atag * k % mod;
121 node[x].mtag = (LL)node[x].mtag * k % mod;
122 node[x].sum = (LL)node[x].sum * k % mod;
123 return;
124 }
125 push_down(x);
126 push_up(x);
127 int mid = (node[x].l + node[x].r) >> 1;
128 if (left <= mid) update_mul(left, right, lc(x), k);
129 if (right > mid) update_mul(left, right, rc(x), k);
130 push_up(x);
131 }
132
133 inline long long int query(int left, int right, int x)
134 {
135 long long int res = 0;
136 if (left <= node[x].l && node[x].r <= right) return node[x].sum;
137 push_down(x);
138 int mid = (node[x].l + node[x].r) >> 1;
139 if (left <= mid) (res += query(left, right, lc(x))) %= mod;
140 if (right > mid) (res += query(left, right, rc(x))) %= mod;
141 return res;
142 }
143
144 int main()
145 {
146 ios::sync_with_stdio(0);
147 cin.tie(0);
148 cout.tie(0);
149 cin >> n >> mod;
150 mfor(i, 1, n)
151 {
152 cin >> a[i];
153 }
154 build(1, 1, n);
155 cin >> m;
156 mfor(i, 1, m)
157 {
158 int t, a, b, c;
159 cin >> t >> a >> b;
160 if (t != 3) cin >> c;
161 if (t == 1) update_mul(a, b, 1, c);
162 if (t == 2) update_add(a, b, 1, c);
163 if (t == 3) cout << query(a, b, 1) << endl;
164 }
165 }