1. 程式人生 > >洛谷 P4256 公主の#19準備月考

洛谷 P4256 公主の#19準備月考

LG pac 質數 radi getchar() long long 最重要的 掛科 name

題目背景

公主在玩完遊戲後,也要月考了。(就算是公主也要月考啊QWQ)

題目描述

公主的文綜太差了,全校排名1100+(全校就1100多人),她分析了好久,發現她如果把所有時間放在選擇題上,得分會比較好一點。

文綜題目共有n個,編號從1到n

公主給每個題目算出來了一個預估值Ai,她認為,一段連續題目的答案會在它們的預估值的gcd和lcm之間;有時候她的想法不同了,一些題目的預估值會改變;有時候,會出現多選題,多選題的答案數量就是一段連續題目答案的預估值的公約數的個數。

具體來說,對於一個數列,有四種操作:

L x y p 表示公主詢問區間[x,y]的數字的lcm對p取模之後的值

G x y p 表示公主詢問區間[x,y]的數字的gcd對p取模之後的值

C x y c 表示公主改變區間[x,y]的數字的值,統一為c

S x y p 表示公主詢問區間[x,y]的數字的公因數個數對p取模之後的值

公主月考不能掛科,不然她就不能學習OI了(假的),所以請你幫幫她吧!

輸入輸出格式

輸入格式:

第一行,兩個正整數n和q,q表示操作次數

第二行,n個正整數,表示dkw對題目的預估值

接下來q行,每行輸入一個操作,格式詳見題目描述

輸出格式:

對於每個詢問,輸出它的答案。

輸入輸出樣例

輸入樣例#1:
10 10
42 68 35 1 70 25 79 59 63 65 
L 2 6 28
L 2 6 43
G 2 7 5
G 3 4 83
L 7 9 96
G 2 7 39
S 3 8 100
L 4 5 12
G 4 4 65
L 2 4 69
輸出樣例#1:
0
32
1
1
75
1
1
10
1
34

說明

對於30%的數據,1<=n,q<=1000

對於另外20%的數據,1<=n<=1000,1<=q<=100000

對於另外20%的數據,1<=n<=100000,1<=q<=100000,保證沒有修改操作

對於100%的數據,1<=n<=300000,1<=q<=300000

保證任何時刻每個題目的預估值都在[1,100]之間,答案取模之後不超過int

最重要的性質是所有數不超過100,所以只有25個質因子。

我們只需要維護一下這25個質因子的質數在區間的min和max就行了。

然後我就卡著常數過去了哈哈哈

技術分享圖片

#include<bits/stdc++.h>
#define ll long long
#define maxn 300005
#define pb push_back
using namespace std;
int zs[30],t=0,d[105];
bool v[105];
int ci[105][30];
int tmp[30][30];
struct node{
	int mx[30],mn[30],tag;
	node operator +(const node &u)const{
		node r;
		r.tag=0;
		for(int i=1;i<=t;i++){
			r.mx[i]=max(mx[i],u.mx[i]);
			r.mn[i]=min(mn[i],u.mn[i]);
		}
		return r;
	}
	
	inline void clear(){
		memset(mx,0,sizeof(mx));
		memset(mn,0x3f,sizeof(mn));
		tag=0;
	}
}b[maxn<<2|1],AN;

inline void init(){
	for(int i=2;i<=100;i++){
		if(!v[i]) zs[++t]=i,ci[i][t]=1;
		for(int j=1,u;j<=t&&(u=zs[j]*i)<=100;j++){
			v[u]=1;
			memcpy(ci[u],ci[i],sizeof(ci[i]));
			ci[u][j]++;
			if(!(i%zs[j])) break;
		}
	}
	/*
	for(int i=1;i<=100;i++){
		for(int j=1;j<=t;j++) printf("%d ",ci[i][j]);
		puts("");
	}
	*/
	
	for(int i=1;i<=100;i++)
	    for(int j=i;j<=100;j+=i) d[j]++;
	
	for(int i=1;i<=t;i++){
		tmp[i][0]=1;
		for(int j=1;;j++){
			tmp[i][j]=tmp[i][j-1]*zs[i];
			if(tmp[i][j]>100) break;
		}
	}
}

int n,m,a[maxn],p;
int opt,le,ri,w;
char ch;

inline void work(int o,int val){
	b[o].tag=val;
	for(int i=1;i<=t;i++) b[o].mn[i]=b[o].mx[i]=ci[val][i];
}

inline void pushdown(int o,int lc,int rc){
	if(b[o].tag){
		work(lc,b[o].tag);
		work(rc,b[o].tag);
		b[o].tag=0;
	}
}

void build(int o,int l,int r){
	if(l==r){
		for(int i=1;i<=t;i++) b[o].mn[i]=b[o].mx[i]=ci[a[l]][i];
		b[o].tag=0;
		return;
	}
	
	int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	
	b[o]=b[lc]+b[rc];
}

void update(int o,int l,int r){
	if(l>=le&&r<=ri){
		work(o,w);
		return;
	}
	
	int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1;
	pushdown(o,lc,rc);
	if(le<=mid) update(lc,l,mid);
	if(ri>mid) update(rc,mid+1,r);
	
	b[o]=b[lc]+b[rc];
}

void query(int o,int l,int r){
	if(l>=le&&r<=ri){
		AN=AN+b[o];
		return;
	}
	
	int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1;
	pushdown(o,lc,rc);
	if(le<=mid) query(lc,l,mid);
	if(ri>mid) query(rc,mid+1,r);
}

int main(){
	init();
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",a+i);
	build(1,1,n);
	
	while(m--){
		ch=getchar();
		while(ch!=‘L‘&&ch!=‘G‘&&ch!=‘C‘&&ch!=‘S‘) ch=getchar();
		scanf("%d%d%d",&le,&ri,&p);
		if(ch==‘C‘){
			w=p;
			update(1,1,n);
		}
		else if(ch==‘S‘){
			AN.clear();
			query(1,1,n);
			int gcd=1;
			for(int i=1;i<=t;i++) gcd=gcd*tmp[i][AN.mn[i]];
			printf("%d\n",d[gcd]%p);
		}
		else if(ch==‘L‘){
			AN.clear();
			query(1,1,n);
			int lcm=1;
			const int ha=p;
			for(int i=1;i<=t;i++) lcm=lcm*(ll)tmp[i][AN.mx[i]]%ha;
			printf("%d\n",lcm);
		}
		else{
			AN.clear();
			query(1,1,n);
			int gcd=1;
			for(int i=1;i<=t;i++) gcd=gcd*tmp[i][AN.mn[i]];
			printf("%d\n",gcd%p);
		}
	}
	
	return 0;
}

  

洛谷 P4256 公主の#19準備月考