CF1493D GCD of an Array 题解

Problem

给出一个长度为 \(n\leq2\times10^5\) 的序列( 每个数 \(\leq 2\times10^5\) ) , 维护以下操作:

  1. 单点乘
  2. 全局 Gcd (对 \(10^9+7\) 取模)

Sol

考虑线段树维护。

首先将每个数质因数分解,每个节点维护每个质因子在每个数中出现最小次数,用 map 存起来即可。

对于更新,我们只要考虑有修改的质因子出现最小次数是否增加就行了。

但是会 TLE on test 7 。

新增优化:

  1. 如果在线段树底层某个质因子出现最小次数没有增加,那么一定不会在上层有改变,舍弃
    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;
}

posted @ 2021-03-07 00:48  Werner_Yin  阅读(52)  评论(0编辑  收藏  举报