#include <bits/stdc++.h>
using namespace std;
struct {
unordered_map<int,int> m;
}seg[2000001];
unordered_map<int,int> merge(unordered_map<int,int> m1,unordered_map<int,int> m2){
unordered_map<int,int> mp=m1;
for(auto i:m2) mp[i.first]+=i.second;
return mp;
}
void build(int a[],int n,int idx,int l,int r,int k){
if(l==r) {seg[idx].m[a[l]%k]++; return;}
build(a,n,2*idx,l,(l+r)/2,k);
build(a,n,2*idx+1,1+(l+r)/2,r,k);
seg[idx].m=merge(seg[idx*2].m,seg[idx*2+1].m);
}
void insert(int idx,int l,int r,int p,int val,int a[],int k){
if(l==r){
seg[idx].m[a[p]%k]--;
seg[idx].m[(a[p]+val)%k]++;
return;
}
int mid=(l+r)/2;
if(p>mid) insert(2*idx+1,mid+1,r,p,val,a,k);
else if(p<=mid) insert(2*idx,l,mid,p,val,a,k);
seg[idx].m=merge(seg[2*idx].m,seg[2*idx+1].m);
}
int query(int idx,int l,int r,int x,int y,int rem){
if(l==x && r==y) {
if(seg[idx].m.find(rem)!=seg[idx].m.end()) return seg[idx].m[rem];
return 0;
}
int mid=(l+r)/2;
if(x>mid) return query(idx*2+1,mid+1,r,x,y,rem);
if(y<=mid) return query(idx*2,l,mid,x,y,rem);
return query(idx*2,l,mid,x,mid,rem)+query(idx*2+1,mid+1,r,mid+1,y,rem);
}
int main() {
int n,q,k,x,l,r,rem,p,val;
cin>>n>>q>>k;
int a[n];
for(int i=0;i<n;i++) cin>>a[i];
build(a,n,1,0,n-1,k);
for(int i=0;i<q;i++){
cin>>x;
if(x==1){
cin>>p>>val;
p-=1;
insert(1,0,n-1,p,val,a,k);
a[p]+=val;
}
else{
cin>>l>>r>>rem;
l-=1,r-=1;
cout<<query(1,0,n-1,l,r,rem)<<endl;
}
}
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CnN0cnVjdCB7Cgl1bm9yZGVyZWRfbWFwPGludCxpbnQ+IG07CQp9c2VnWzIwMDAwMDFdOwp1bm9yZGVyZWRfbWFwPGludCxpbnQ+IG1lcmdlKHVub3JkZXJlZF9tYXA8aW50LGludD4gbTEsdW5vcmRlcmVkX21hcDxpbnQsaW50PiBtMil7Cgl1bm9yZGVyZWRfbWFwPGludCxpbnQ+IG1wPW0xOwoJZm9yKGF1dG8gaTptMikgbXBbaS5maXJzdF0rPWkuc2Vjb25kOwoJcmV0dXJuIG1wOwp9CnZvaWQgYnVpbGQoaW50IGFbXSxpbnQgbixpbnQgaWR4LGludCBsLGludCByLGludCBrKXsKCWlmKGw9PXIpIHtzZWdbaWR4XS5tW2FbbF0la10rKzsgcmV0dXJuO30KCWJ1aWxkKGEsbiwyKmlkeCxsLChsK3IpLzIsayk7CglidWlsZChhLG4sMippZHgrMSwxKyhsK3IpLzIscixrKTsKCXNlZ1tpZHhdLm09bWVyZ2Uoc2VnW2lkeCoyXS5tLHNlZ1tpZHgqMisxXS5tKTsKfQp2b2lkIGluc2VydChpbnQgaWR4LGludCBsLGludCByLGludCBwLGludCB2YWwsaW50IGFbXSxpbnQgayl7CglpZihsPT1yKXsKCQlzZWdbaWR4XS5tW2FbcF0la10tLTsKCQlzZWdbaWR4XS5tWyhhW3BdK3ZhbCkla10rKzsKCQlyZXR1cm47Cgl9CglpbnQgbWlkPShsK3IpLzI7CglpZihwPm1pZCkgaW5zZXJ0KDIqaWR4KzEsbWlkKzEscixwLHZhbCxhLGspOwoJZWxzZSBpZihwPD1taWQpIGluc2VydCgyKmlkeCxsLG1pZCxwLHZhbCxhLGspOwoJc2VnW2lkeF0ubT1tZXJnZShzZWdbMippZHhdLm0sc2VnWzIqaWR4KzFdLm0pOwp9CmludCBxdWVyeShpbnQgaWR4LGludCBsLGludCByLGludCB4LGludCB5LGludCByZW0pewoJaWYobD09eCAmJiByPT15KSB7CgkgICAgaWYoc2VnW2lkeF0ubS5maW5kKHJlbSkhPXNlZ1tpZHhdLm0uZW5kKCkpIHJldHVybiBzZWdbaWR4XS5tW3JlbV07CgkJcmV0dXJuIDA7Cgl9CglpbnQgbWlkPShsK3IpLzI7CglpZih4Pm1pZCkgcmV0dXJuIHF1ZXJ5KGlkeCoyKzEsbWlkKzEscix4LHkscmVtKTsKCWlmKHk8PW1pZCkgcmV0dXJuIHF1ZXJ5KGlkeCoyLGwsbWlkLHgseSxyZW0pOwoJcmV0dXJuIHF1ZXJ5KGlkeCoyLGwsbWlkLHgsbWlkLHJlbSkrcXVlcnkoaWR4KjIrMSxtaWQrMSxyLG1pZCsxLHkscmVtKTsKfQppbnQgbWFpbigpIHsKCWludCBuLHEsayx4LGwscixyZW0scCx2YWw7CgljaW4+Pm4+PnE+Pms7CglpbnQgYVtuXTsKCWZvcihpbnQgaT0wO2k8bjtpKyspIGNpbj4+YVtpXTsKCWJ1aWxkKGEsbiwxLDAsbi0xLGspOwoJZm9yKGludCBpPTA7aTxxO2krKyl7CgkJY2luPj54OwoJCWlmKHg9PTEpewoJCQljaW4+PnA+PnZhbDsKCQkJcC09MTsKCQkJaW5zZXJ0KDEsMCxuLTEscCx2YWwsYSxrKTsKCQkJYVtwXSs9dmFsOwoJCX0KCQllbHNlewoJCQljaW4+Pmw+PnI+PnJlbTsKCQkJbC09MSxyLT0xOwoJCQljb3V0PDxxdWVyeSgxLDAsbi0xLGwscixyZW0pPDxlbmRsOwoJCX0KCX0KCXJldHVybiAwOwp9