#include <bits/stdc++.h>
#define inline il
using namespace std;
typedef long long ll;
const ll N = 1e5 + 100;
const ll T = 4 * N + 100;
ll a[N] , n , m , q;
ll tree[T] , lazy[T];
ll lazy2[T];
void buildtree(ll l , ll r , ll p)
{
lazy2[p] = 1;
if(l == r)
{
tree[p] = a[l] % m;
return;
}
ll mid = (l + r) >> 1;
buildtree(l , mid , p * 2);
buildtree(mid + 1 , r , p * 2 + 1);
tree[p] = tree[p * 2] + tree[p * 2 + 1] , tree[p] %= m;
}
void pushdown(ll findl , ll findr , ll mid , ll p)
{
if(lazy2[p] != 1 && findl != findr)
{
tree[p * 2] *= lazy2[p] , tree[p * 2] %= m;
tree[p * 2 + 1] *= lazy2[p] , tree[p * 2 + 1] %= m;
lazy2[p * 2] *= lazy2[p] , lazy2[p * 2] %= m;
lazy2[p * 2 + 1] *= lazy2[p] , lazy2[p * 2 + 1] %= m;
lazy[p * 2] *= lazy2[p];
lazy[p * 2 + 1] *= lazy2[p];
lazy2[p] = 1;
}
if(lazy[p] && findl != findr)
{
tree[p * 2] += (mid - findl + 1) * lazy[p] , tree[p * 2] %= m;
tree[p * 2 + 1] += (findr - mid) * lazy[p] , tree[p * 2 + 1] %= m;
lazy[p * 2] += lazy[p] , lazy[p * 2] %= m;
lazy[p * 2 + 1] += lazy[p] , lazy[p * 2 + 1] %= m;
lazy[p] = 0;
}
}
ll getsum(ll l , ll r , ll findl , ll findr , ll p)
{
if(l <= findl && findr <= r)
{
return tree[p];
}
ll mid = (findl + findr) >> 1 , sum = 0;
pushdown(findl , findr , mid , p);
if(l <= mid)
sum += getsum(l , r , findl , mid , p * 2) , sum %= m;
if(r > mid)
sum += getsum(l , r , mid + 1 , findr , p * 2 + 1) , sum %= m;
return sum % m;
}
void update(ll l , ll r , ll findl , ll findr , ll delta , ll p)
{
if(l <= findl && findr <= r)
{
tree[p] += (findr - findl + 1) * delta , tree[p] %= m;
lazy[p] += delta , lazy[p] %= m;
return;
}
ll mid = (findl + findr) >> 1;
pushdown(findl , findr , mid , p);
if(l <= mid)
update(l , r , findl , mid , delta , p * 2);
if(r > mid)
update(l , r , mid + 1 , findr , delta , p * 2 + 1);
tree[p] = tree[p * 2] + tree[p * 2 + 1] , tree[p] %= m;
}
void updatetime(ll l , ll r , ll findl , ll findr , ll delta , ll p)
{
if(l <= findl && findr <= r)
{
tree[p] *= delta , tree[p] %= m;
lazy2[p] *= delta , lazy2[p] %= m;
lazy[p] *= delta , lazy[p] %= m;
return;
}
ll mid = (findl + findr) >> 1;
pushdown(findl , findr , mid , p);
if(l <= mid)
updatetime(l , r , findl , mid , delta , p * 2);
if(r > mid)
updatetime(l , r , mid + 1 , findr , delta , p * 2 + 1);
tree[p] = tree[p * 2] + tree[p * 2 + 1] , tree[p] %= m;
}
signed main(){
cin >> n >> q >> m;
for(ll i = 1;i <= n;i++) cin >> a[i];
buildtree(1 , n , 1);
for(ll i = 1;i <= q;i++)
{
ll ch;
cin >> ch;
if(ch == 1)
{
ll x , y , k;
cin >> x >> y >> k;
updatetime(x , y , 1 , n , k , 1);
}
if(ch == 2)
{
ll x , y , k;
cin >> x >> y >> k;
update(x , y , 1 , n , k , 1);
}
if(ch == 3)
{
ll x , y;
cin >> x >> y;
cout << getsum(x , y , 1 , n , 1) % m << endl;
}
}
return 0;
}