• 洛谷 P4256 公主の#19准备月考


    题目背景

    公主在玩完游戏后,也要月考了。(就算是公主也要月考啊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
    ",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
    ",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
    ",gcd%p);
    		}
    	}
    	
    	return 0;
    }
    

      

  • 相关阅读:
    运维:生产日志重复打印了,赶紧来看看~
    就这样,我走过了程序员的前五年。一路风雨泥泞,前方阳光正好。
    一个排序引发的BUG
    曝光一个网站,我周末就耗在上面了。
    我不服!这开源项目居然才888个星!?
    知乎的一次29.7元的咨询
    面试官:啥是请求重放呀?
    414天前,我以为这是编程玄学...
    老爷子这代码,看跪了!
    面试官一个线程池问题把我问懵逼了。
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8490351.html
Copyright © 2020-2023  润新知