解析:
套路題
v非常的小而且我們找約數的個數,那麼肯定想到唯一分解定理。通過唯一分解,我們只要維護2,3,5,7 這四個數出現的次數。
用二維線段樹維護這4個數出現的次數
查詢的時候只要通過唯一分解定理公式即可求解
加粗樣式
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int N=1e5+1000;
typedef long long ll;
ll tr[N<<2][10];
ll res[N];
int n,q,op,l,r;
ll a[N];
void push_up(int u)
{
for(int i=2;i<=9;i++) tr[u][i]=(tr[u<<1][i]+tr[u<<1|1][i])%MOD;
}
void build(int u,int l,int r)
{
if(l==r)
{
tr[u][2]=tr[u][3]=tr[u][5]=tr[u][7]=0;
ll x=a[l];
for(int i=2;i*i<=x;i++)
{
while(x%i==0) tr[u][i]++,x/=i;
}
if(x>1) tr[u][x]++;
return ;
}
int mid=l+r>>1;
build(u<<1,l,mid);build(u<<1|1,mid+1,r);
push_up(u);
}
void update(int u,int l,int r,int x,int val)
{
if(l==r)
{
tr[u][2]=tr[u][3]=tr[u][5]=tr[u][7]=0;
for(int i=2;i*i<=val;i++)
{
while(val%i==0) tr[u][i]++,val/=i;
}
if(val>1) tr[u][val]++;
return ;
}
int mid=l+r>>1;
if(x<=mid) update(u<<1,l,mid,x,val);
else update(u<<1|1,mid+1,r,x,val);
push_up(u);
}
void query(int u,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)
{
for(int i=2;i<=9;i++) res[i]+=tr[u][i];
return ;
}
int mid=l+r>>1;
if(ql<=mid) query(u<<1,l,mid,ql,qr);
if(qr>mid) query(u<<1|1,mid+1,r,ql,qr);
}
int main()
{
scanf("%d %d",&n,&q);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
build(1,1,n);
while(q--)
{
scanf("%d %d %d",&op,&l,&r);
if(op==1) update(1,1,n,l,r);
else
{
for(int i=1;i<=10;i++) res[i]=0;
ll ans=1;
query(1,1,n,l,r);
for(int i=2;i<=9;i++) ans=(ans*(res[i]+1))%MOD;
printf("%lld\n",ans);
}
}
}