洛谷 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
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準備月考