#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n,m;
int a[N];
vector<int> v;
namespace segment{
struct stu{
long long val;
}tree[N<<2];
int ls(int xx){
return xx*2;
}
int rs(int xx){
return xx*2+1;
}
void pushup(int x){
tree[x].val=tree[ls(x)].val+tree[rs(x)].val;
}
void build(int now,int l,int r){
if(l==r){
tree[now].val=a[l];
return;
}
int mid=(l+r)>>1;
build(ls(now),l,mid);
build(rs(now),mid+1,r);
pushup(now);
}
void update(int now,int l,int r,int pla,int val){
if(l==r && l==pla){
tree[now].val+=val;
return;
}
int mid=(l+r)>>1;
if(pla<=mid) update(ls(now),l,mid,pla,val);
else update(rs(now),mid+1,r,pla,val);
pushup(now);
}
long long query(int now,int l,int r,int ll,int rr){
if(l>=ll && r<=rr){
return tree[now].val;
}
int mid=(l+r)>>1;
long long res=0;
if(ll<=mid) res+=query(ls(now),l,mid,ll,rr);
if(rr>mid) res+=query(rs(now),mid+1,r,ll,rr);
return res;
}
}
int root[500010];
namespace treap{
int tot;
struct node{
int lc,rc,val,rnk,size;
}tree[N*200];
void update(int k){
tree[k].size=tree[tree[k].lc].size+tree[tree[k].rc].size+1;
}
void split(int k,int &a,int &b,int val){
if(k==0){
a=b=0;
return;
}
else if(tree[k].val<=val){
a=k;
split(tree[k].rc,tree[k].rc,b,val);
}
else{
b=k;
split(tree[k].lc,a,tree[k].lc,val);
}
update(k);
return;
}
void merge(int &k,int a,int b){
if(a==0 || b==0){
k=a+b;
return;
}
else if(tree[a].rnk<=tree[b].rnk){
k=a;
merge(tree[k].rc,tree[k].rc,b);
}
else{
k=b;
merge(tree[k].lc,a,tree[k].lc);
}
update(k);
return;
}
int add_node(int val){
tree[++tot].val=val;
tree[tot].lc=tree[tot].rc=0;
tree[tot].size=1;
tree[tot].rnk=rand();
return tot;
}
void insert(int &k,int val){
int a,b,cur;
split(k,a,b,val);
cur=add_node(val);
merge(a,a,cur);
merge(k,a,b);
return;
}
void pre_treap(){
for(int i=1;i<=n;i++){
for(int j=2;j<=sqrt(a[i]);j++){
if(!(a[i]%j)){
insert(root[j],i);
if((j*j)!=a[i]){
insert(root[a[i]/j],i);
}
}
}
insert(root[a[i]],i);
}
}
void dfs(int now,int x){
if(!now) return;
if(!(a[tree[now].val]%x)) v.push_back(now);
dfs(tree[now].lc,x);
dfs(tree[now].rc,x);
}
int get(int x){
return tree[x].val;
}
void work(int l,int r,int x){
int a,b,c;
split(root[x],a,b,l-1);
split(b,b,c,r);
merge(a,a,c);
dfs(b,x);
root[x]=a;
}
}
inline int read(){
char ch;int x=0;bool f=false;
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=true;
for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
if(f) x=-x;
return x;
}
void work(int opt,int l,int r,int x){
if(x==1) return;
else{
v.clear();
treap::work(l,r,x);
if(!v.size()) return;
for(int i=0;i<v.size();i++){
int ops=v[i];
segment::update(1,1,n,treap::get(ops),(a[treap::get(ops)]/x)-a[treap::get(ops)]);
a[treap::get(ops)]/=x;
if(!(a[treap::get(ops)]%x)) treap::insert(root[x],ops);
}
return;
}
}
int main(){
srand(time(0));
n=read(),m=read();
for(int i=1;i<=n;i++) a[i]=read();
segment::build(1,1,n);
treap::pre_treap();
int opt,l,r,x;
while(m--){
opt=read(),l=read(),r=read();
if(opt==1){
x=read();
work(opt,l,r,x);
}
else{
cout<<segment::query(1,1,n,l,r)<<"\n";
}
}
return 0;
}