智乃與無意義的題目----------------------------------思維(二維線段樹+性質+套路題)

在這裏插入圖片描述
在這裏插入圖片描述
解析:
套路題
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);
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章