my code:
#include <bits/stdc++.h>
using namespace std ;
const int N = 1e5 + 10;
const long long int Mod = 998244353 ;
struct Node{
int l , r ;
bool ex[100];
long long mul ;
long long sum ;
};
Node tr[N*4] ;
int Ww[30];
int primes[25] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
int n , m ;
void Divide(int w[] , int W , int& len)
{
len = 0 ;
for(int prime : primes)
{
while(W % prime == 0)
{
w[len++] = prime;
W /= prime ;
}
if(W == 1)break;
}
}
void push_up(int u){
tr[u].sum = (tr[u << 1].sum + tr[u << 1 | 1].sum) % Mod;
for(int prime : primes){
tr[u].ex[prime] = tr[u << 1].ex[prime] && tr[u << 1 | 1].ex[prime];
}
}
void down(int u)
{
tr[u].sum = (tr[u].sum * tr[u>>1].mul) % Mod ;
tr[u].mul = (tr[u].mul * tr[u>>1].mul) % Mod ;
}
void push_down(int u)
{
if(tr[u].mul > 1){
down(u << 1) ;
down(u << 1 | 1) ;
tr[u].mul = 1 ;
}
}
void build(int u, int l , int r)
{
tr[u].l = l , tr[u].r = r , tr[u].mul = 1;
tr[u].ex[1] = true ;
if(l == r){
tr[u].sum = 1 ;
}else{
int mid = (l + r) >> 1 ;
build(u << 1 , l , mid);
build(u << 1 | 1 , mid + 1 , r) ;
tr[u].sum = (tr[u << 1].sum + tr[u << 1 | 1].sum) % Mod;
}
}
bool check(int u , const int w[], int wlen)
{
for(int i = 0 ; i < wlen ; i++){
if(tr[u].ex[w[i]] == false)return false ;
}
return true ;
}
void update(int u , int L , int R , int W , const int w[] , int wlen)
{
if(L <= tr[u].l && tr[u].r <= R){
if(tr[u].l == tr[u].r){
for(int i = 0 ; i < wlen ; i++){
if(tr[u].ex[w[i]] == true) tr[u].sum = (tr[u].sum * w[i]) % Mod ;
else tr[u].sum = (tr[u].sum * (w[i] - 1)) % Mod , tr[u].ex[w[i]] = true;
}
}else{
if(check(u , w , wlen)) {
tr[u].sum = (tr[u].sum * W) % Mod ;
tr[u].mul = (tr[u].mul * W) % Mod ;
}else{
push_down(u);
update(u << 1 , L , R , W , w , wlen);
update(u << 1 | 1 , L , R , W , w , wlen);
push_up(u) ;
}
}
}else{
int mid = (tr[u].l + tr[u].r) >> 1 ;
push_down(u);
if(mid >= L) update(u << 1 , L , R , W , w , wlen);
if(mid + 1 <= R) update(u << 1 | 1 , L , R , W , w , wlen);
push_up(u);
}
}
long long int query(int u , int L , int R)
{
if(L <= tr[u].l && tr[u].r <= R) return tr[u].sum ;
else {
push_down(u) ;
int mid = (tr[u].l + tr[u].r) >> 1;
long long int ans = 0 ;
if(mid >= L) ans = (ans + query(u << 1 , L, R)) % Mod ;
if(mid + 1 <= R) ans = (ans + query(u << 1 | 1 , L , R)) % Mod ;
return ans % Mod;
}
}
signed main()
{
// freopen("in","r",stdin);
// freopen("out2","w",stdout);
scanf("%d%d",&n,&m);
build(1 , 1 , n) ;
for(int i = 1 ; i <= n ; i++)
{
int x ;
scanf("%d",&x) ;
if(x == 1) continue;
int len ;
Divide(Ww,x,len);
update(1 , i , i , x , Ww , len);
}
for(int i = 1 ; i <= m ; i++)
{
int op , l , r , w ;
scanf("%d",&op) ;
if(op == 0)
{
scanf("%d%d%d",&l,&r,&w) ;
int len ;
if(w == 1) continue;
Divide(Ww , w , len) ;
update(1 , l , r , w , Ww , len);
}else if(op == 1){
scanf("%d%d",&l,&r) ;
printf("%lld\n", query(1 , l , r) % Mod) ;
}
}
return 0 ;
}