/*
区间操作,可以推一推式子,方差为平方的平均数-平均数的平方,维护区间和与区间平方和,平方和的维护方法类似,式子推一推就行了,注意约分
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define ll long long
#define fo(i,l,r) for(int i = l;i <= r;i++)
#define fd(i,l,r) for(int i = r;i >= l;i--)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int N = 100050;
ll read(){
ll x=0,f=1;
char ch=getchar();
while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();};
while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();};
return x*f;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
struct fs{
ll son;
ll mo;
void yf(){
if(son == 0 || mo == 0){
if(son == 0) mo = 1;
return;
}
ll d = gcd(son,mo);
son /= d;
mo /= d;
}
void clear(ll a,ll b){
son = a;
mo = b;
yf();
}
fs operator + (fs b){
fs a=*this;
ll d = gcd(a.mo,b.mo);
ll lcm = a.mo / d * b.mo;
a.son *= lcm / a.mo;
b.son *= lcm / b.mo;
a.son += b.son;
a.mo = lcm;
a.yf();
return a;
}
fs operator - (fs b){
fs a=*this;
ll d = gcd(a.mo,b.mo);
ll lcm = a.mo / d * b.mo;
a.son *= lcm / a.mo;
b.son *= lcm / b.mo;
a.son -= b.son;
a.mo = lcm;
if(!a.son) a.mo = 1;
else a.yf();
return a;
}
fs operator * (fs b){
fs a=*this;
a.son *= b.son;
a.mo *= b.mo;
a.yf();
return a;
}
fs operator / (ll b){
fs a =*this;
a.mo *= b;
a.yf();
return a;
}
bool operator < (fs b){
return son*b.mo < mo*b.son;
}
fs operator - (ll k){
fs b,a=*this;
b.clear(k,1);
if(a<b) swap(a,b);
return a-b;
}
void print(){
printf("%I64d/%I64d\n",son,mo);
}
}ans,fd;
int n,m;ll val[N];
ll sumv[N<<4],addv[N<<4],powv[N<<4];
ll cmd,op,ql,qr,qv,ans1,ans2;
void maintain(int rt){
sumv[rt] = sumv[rt<<1] + sumv[rt<<1|1];
powv[rt] = powv[rt<<1] + powv[rt<<1|1];
}
void pushdown(int l,int r,int rt){
int m = (l + r) >> 1;
if(!addv[rt]) return;
addv[rt<<1] += addv[rt];
addv[rt<<1|1] += addv[rt];
powv[rt<<1] += 2*addv[rt]*sumv[rt<<1] + (m-l+1)*addv[rt]*addv[rt];
powv[rt<<1|1] += 2*addv[rt]*sumv[rt<<1|1] + (r-m)*addv[rt]*addv[rt];
sumv[rt<<1] += addv[rt] * (m-l+1);
sumv[rt<<1|1] += addv[rt] * (r-m);
addv[rt] = 0;
}
void build(int l,int r,int rt){
addv[rt] = 0;
if(l==r){
powv[rt] = val[l]*val[l];
sumv[rt] = val[l];
return;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
maintain(rt);
}
void change(ll l,ll r,int rt){
if(ql <= l && qr >= r){
addv[rt] += qv;
powv[rt] += 2*qv*sumv[rt] + qv*qv*(r-l+1);
sumv[rt] += qv*(r-l+1);
return;
}
pushdown(l,r,rt);
int m = (l + r) >> 1;
if(ql <= m) change(lson);
if(qr > m) change(rson);
maintain(rt);
}
ll query(int l,int r,int rt){
if(ql <= l && qr >= r){
if(op == 1) return sumv[rt];
else return powv[rt];
}
pushdown(l,r,rt);
int m = (l + r) >> 1;
ll ret = 0;
if(ql <= m) ret += query(lson);
if(qr > m) ret += query(rson);
return ret;
}
int main(){
freopen("classroom.in","r",stdin);
freopen("classroom.out","w",stdout);
n =read();m=read();
fo(i,1,n) val[i]=read();
build(1,n,1);
fo(i,1,m){
cmd=read();ql=read();qr=read();
if(cmd==1){
qv=read();
change(1,n,1);
}else if(cmd == 2){
op = 1;
ans1=query(1,n,1);
ans2=(qr-ql+1);
ans.clear(ans1,ans2);
ans.print();
}else if(cmd == 3){
op = 2;
ans1=query(1,n,1);
ans2=(qr-ql+1);
ans.clear(ans1,ans2);
ans1=ans2=0;
op = 1;
ans1=query(1,n,1);
ans2=(qr-ql+1);
fd.clear(ans1,ans2);
fd = fd*fd;
ans = ans-fd;
ans.print();
}
}
return 0;
}