题目背景
公主在玩完游戏后,也要月考了。(就算是公主也要月考啊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; }
原文地址:https://www.cnblogs.com/JYYHH/p/8490351.html