小花梨的数组
Description
小花梨得到了一个长度为𝑛的数组𝑎,现在要对它进行三种操作:
⚫ 1 𝑙 𝑟 对所有的𝑖 ∈ [𝑙, 𝑟], 𝑎[𝑖] = 𝑎[𝑖] ∗ 𝑚𝑖𝑛𝑝𝑟𝑖𝑚𝑒(𝑎[𝑖])
⚫ 2 𝑙 𝑟 对所有的𝑖 ∈ [𝑙, 𝑟], 𝑎[𝑖] = 𝑎[𝑖] / 𝑚𝑖𝑛𝑝𝑟𝑖𝑚𝑒(𝑎[𝑖])
⚫ 3 𝑥 求𝑎[𝑥]的值 𝑚𝑖𝑛𝑝𝑟𝑖𝑚𝑒(𝑥) = { 1 (𝑥 = 1) 𝑥的最小素因子(𝑥 ≥ 2) 现在给出初始数组𝑎,对其进行𝑚次操作,对于第三种操作输出结果。
𝑚𝑖𝑛𝑝𝑟𝑖𝑚𝑒(𝑥) = { 1 (𝑥 = 1) , 𝑥的最小素因子(𝑥 ≥ 2)}
现在给出初始数组𝑎,对其进行𝑚次操作,对于第三种操作输出结果。
Input
第一行输入两个正整数𝑛, 𝑚,表示数组的长度以及操作次数(1 ≤ 𝑛, 𝑚 ≤ 100000)
第二行输入𝑛个正整数表示数组𝑎(1 ≤ 𝑎𝑖 ≤ 1000000) 接下来𝑚行表示𝑚次操作,每行输入格式为"1 𝑙 𝑟"或者"2 𝑙 𝑟",或者"3 𝑥",对应上述三种操作1 ≤ 𝑙, 𝑟, 𝑥 ≤ 𝑛, 𝑙 ≤ r
Output
对于第三种操作输出答案即可,答案对10 9 + 7进行取模。
Sample Input
5 8
1 2 3 4 5
1 2 4
3 2
3 3
2 2 5
3 2
3 5
1 5 5
3 5
Sample Output
4
9
2
1
1
解题思路:用线段树+lazy标志去维护每个点操作了多少次,乘的时候tag值加1,除的时候tag值-1。当tag值为-1的时候更新这个点。
#include <bits/stdc++.h> using namespace std; #define N 100005 #define ll long long vector<int>vec[100005]; int c[100005],d[100005]; struct node { int l,r,w,f,tag; }tree[4*N+5]; ll aaa,bbb; const ll mod=1e9+7; ll quick(ll n,ll m) { ll ans=1; ll c=mod; n=n%c; while(m>0) { if(m&1) ans=(ans*n)%c; n=(n*n)%c; m>>=1; } return ans; } void build(int k,int l,int r) { tree[k].l=l,tree[k].r=r; if(l==r) { scanf("%d",&tree[k].w); c[l]=tree[k].w; return; } int mid=(l+r)>>1; build(k*2,l,mid); build(k*2+1,mid+1,r); } void down(int k) { tree[2*k].tag+=tree[k].tag; tree[2*k+1].tag+=tree[k].tag; tree[k].tag=0; }//下传标记 void min_prime(int pos,int k) { int i=2; while(i*i<=k) { if(k%i==0) { while(k%i==0) { k=k/i; vec[pos].push_back(i); } } i++; } if(k>1) vec[pos].push_back(k); } void change(int k) { if(tree[k].l==tree[k].r) { tree[k].tag=0; if(tree[k].w!=1) { int m_prime=vec[tree[k].l][d[tree[k].l]]; d[tree[k].l]++; tree[k].w=tree[k].w/m_prime; if(tree[k].w==1) tree[k].tag=10000; } return; } if(tree[k].tag==-1) down(k); if(tree[2*k].tag==-1) change(2*k); if(tree[2*k+1].tag==-1) change(2*k+1); } void change_interval(int k,int l,int r,int c) { if(tree[k].l>=l&&tree[k].r<=r) { tree[k].tag+=c; if(tree[k].tag==-1) change(k); return; } if(tree[k].tag) down(k); int m=(tree[k].l+tree[k].r)/2; if(l<=m) change_interval(k*2,l,r,c); if(r>m) change_interval(k*2+1,l,r,c); } void ask_point(int k,int x) { if(tree[k].l==tree[k].r) { aaa=tree[k].w; bbb=tree[k].tag; return ; } if(tree[k].tag) down(k); int m=(tree[k].l+tree[k].r)/2; if(x<=m) ask_point(k*2,x); else ask_point(k*2+1,x); } int main() { int n,m; scanf("%d%d",&n,&m); build(1,1,n); for(int i=1;i<=n;i++) min_prime(i,c[i]); while(m--) { int p,a,b; scanf("%d",&p); if(p==1) { scanf("%d%d",&a,&b); change_interval(1,a,b,1); } else if(p==2) { scanf("%d%d",&a,&b); change_interval(1,a,b,-1); } else { int kk; scanf("%d",&kk); ask_point(1,kk); if(aaa==1) cout<<"1\n"; else { int m_prime=vec[kk][d[kk]]; ll sum=aaa*quick(m_prime,bbb)%mod; cout<<sum<<endl; } } } }

浙公网安备 33010602011771号