CF1493D GCD of an Array 题解
Problem
给出一个长度为 \(n\leq2\times10^5\) 的序列( 每个数 \(\leq 2\times10^5\) ) , 维护以下操作:
- 单点乘
- 全局 Gcd (对 \(10^9+7\) 取模)
Sol
考虑线段树维护。
首先将每个数质因数分解,每个节点维护每个质因子在每个数中出现最小次数,用 map 存起来即可。
对于更新,我们只要考虑有修改的质因子出现最小次数是否增加就行了。
但是会 TLE on test 7 。
新增优化:
- 如果在线段树底层某个质因子出现最小次数没有增加,那么一定不会在上层有改变,舍弃
2. 预处理每个数分解的结果
Code
#define in read()
#define fi first
#define se second
#define pb push_back
#define vec vector<int>
#define pii pair<int,int>
#define vep vector<pii>
#define umap map<int,int>
typedef long long ll;
int read(){int x = 0,sgn = 1;char ch = getchar(); for(;!isdigit(ch);ch=getchar())if(ch=='-')sgn=-1;for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+(ch^48);return x*sgn;}
const int N = 2e5+10;
const int mod = 1e9+7;
int pnum,prime[N],n,a[N],q,id[N];
bool v[N];
ll ans = 1;
vep s[N];
struct node{umap v;}t[N<<2];
umap :: iterator it;
void shai(){
for(int i = 2;i < N;i++){
if(!v[i]) prime[++pnum] = i,id[i] = pnum;
for(int j = 1,x;j <= pnum && prime[j] * i < N;j++){
v[x = prime[j] * i] = 1;
if(i % prime[j] == 0) break;
}
}
}
inline vep divide(int x){
vep t;
if(!v[x]) {
t.pb(pii(id[x],1));
return t;
}
for(int i = 1;i <= pnum && x > 1;i++){
if(x % prime[i] == 0){
pii res = pii(i,0);
while(x % prime[i] == 0) res.se++,x /= prime[i];
t.pb(res);
if(x == 1) break;
if(!v[x]) {
t.pb(pii(id[x],1));
break;
}
}
}return t;
}
void build(int o = 1,int l = 1,int r = n){
if(l == r){
vep pp = s[a[l]];
for(pii x : pp) t[o].v[x.fi] += x.se;
return;
}
int mid = l+r>>1;
build(o<<1,l,mid); build(o<<1|1,mid+1,r);
for(pii d : t[o<<1].v) t[o].v[d.fi] = min(d.se,t[o<<1|1].v[d.fi]);
}
void update(int pos,vep &v,int o = 1,int l = 1,int r = n){
if(l == r){
for(pii x : v) t[o].v[x.fi] += x.se;
return;
}
int mid = l+r>>1;
if(pos <= mid) update(pos,v,o<<1,l,mid);
else if(pos > mid) update(pos,v,o<<1|1,mid+1,r);
vep lef;
for(pii x : v)
if(min(t[o<<1].v[x.fi],t[o<<1|1].v[x.fi]) > t[o].v[x.fi]) t[o].v[x.fi] = min(t[o<<1].v[x.fi],t[o<<1|1].v[x.fi]),lef.pb(x);
v = lef;
}
ll qp(ll x,int t){ll res=1;for(;t;t>>=1,x=x*x%mod)if(t&1)res=res*x%mod;return res;}
int main(){
shai();
for(int i = 2;i < N;i++) s[i] = divide(i);
n = in,q = in;
for(int i = 1;i <= n;i++) a[i] = in;
build(); for(pii x:t[1].v) if(x.se >= 1) ans = ans * qp(prime[x.fi],x.se) % mod;
for(int i = 1;i <= q;i++){
int pos = in,x = in;
if(x != 1) {
vep tmp = s[x],tt = tmp;
for(pii &y : tt) y.se = t[1].v[y.fi];
update(pos,tmp);
for(pii &y : tt)
if(t[1].v[y.fi] > y.se) ans = qp(prime[y.fi],t[1].v[y.fi]-y.se) * ans % mod;
}
printf("%lld\n",ans);
}
return 0;
}
本博客作者:Werner_Yin(https://www.cnblogs.com/werner-yin/) ,转载时请注明出处,谢谢支持!