//剪枝
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
#include<iomanip>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define ll long long
#define mod 998244353
#define INF 0x7fffffffffffffff
#define _maxx 100005
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
ll arr[_maxx<<2],tree[_maxx<<2], maxx[_maxx<<2];
void push_up(int rt)
{
tree[rt] = tree[lson] + tree[rson];
maxx[rt] = max(maxx[lson], maxx[rson]);
}
void build(int l, int r, int rt)
{
if(l == r)
{
tree[rt] = arr[l];
maxx[rt] = arr[l];
return;
}
int mid = (l+r)>>1;
build(l, mid, lson);
build(mid+1, r, rson);
push_up(rt);
}
void update(int l, int r, int idx, int val, int rt)
{
if(l == r)
{
tree[rt] = val;
maxx[rt] = val;
arr[rt] = val;
return;
}
int mid = (l+r)>>1;
if(idx <= mid)
update(l, mid, idx, val, lson);
else
update(mid+1, r, idx, val, rson);
push_up(rt);
}
ll query(int l, int r, int L, int R, int rt)
{
if(L<=l && R>=r)
{
return tree[rt];
}
int mid = (l+r) >>1;
ll sum = 0;
if(L<=mid)
sum += query(l, mid, L, R, lson);
if(R>mid)
sum += query(mid+1, r, L, R, rson);
return sum;
}
void update_mod(int l, int r, int L, int R, int _mod, int rt)
{
if(L<=l && R>=r)
{
if(maxx[rt] < _mod)
return;
if(l == r)
{
tree[rt] %= _mod;
maxx[rt] %= _mod;
return;
}
}
int mid = (l+r)>>1;
if(L<=mid)
update_mod(l, mid, L, R, _mod, lson);
if(R>mid)
update_mod(mid+1, r, L, R, _mod, rson);
push_up(rt);
}
int main (void)
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cin.tie(0);
int n,m,x,l,r,_mod;
cin>>n>>m;
for(int i=1; i<=n; i++)
cin>>arr[i];
build(1, n, 1);
while(m--)
{
cin>>x>>l>>r;
int _mod;
if(x == 1)
cout<<query(1, n, l, r, 1)<<endl;
else if(x == 2)
cin>>_mod, update_mod(1, n, l, r, _mod, 1);
else if(x == 3)
update(1, n, l, r, 1);
}
return 0;
}