D. GCD of an Array

D. GCD of an Array

https://codeforces.ml/contest/1493/problem/D

题目大意

给出一个序列A,之后有q次查询
每次查询给出i和x,使得A[i] = A[i] * x
输出此时序列中所有数的最大公因数。

解题思路

因为题目数据量太大,考虑质因子分解,将这个序列的所有值进行质因子分解

使用容器存储每个质因子对应每个数的幂数,并使用二维map记录其对应幂数(mp[i][j]表示第i个数中j的幂数)便于后面查询时使用
如果某个质因子p所在的容器的长度为n,则说明序列中所有数的因子中都有p,则p对gcd的贡献为pj,j为p所在容器中的最小值,即p的最小幂数(将此时的j记录用于查询使用)

对于每次询问给出的i和x,将x进行质因子分解

对于某个质因子p,先将其对应于i的幂数清除,再重新记录
此时的贡献为pj-j',j表示此时的容器内最小值,j'表示上次计算其贡献时的幂数,如此即可消除上次计算其贡献的影响只考虑此时的贡献。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define req(i,a,b) for(int i=a;i>=b;i--)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N = 2e5+7;
const ll mod = 1e9+7;  
map<int,int>mp[N];
multiset<int>s[N];
vector<int>prime;
map<int,int>check;
int pre[N];
void init(){
    check[1]=check[0]=1;
    for (int i = 2; i < N; ++i)
    {
        if(!check[i])prime.push_back(i);
        for (int j : prime)
        {
            if(i*j>=N)break;
            check[i*j]=1;
            if(i%j==0)break;
        }
    }
}
ll ksm(ll x,ll y){
    ll p=1;
    while(y){
        if(y&1)p=p*x%mod;
        x=x*x%mod;
        y>>=1;
    }return p;
}
int main(){ 
    IO;
    init();
    int n,q;
    cin>>n>>q;
    for (int i = 1; i <= n; ++i)
    {
        int x;
        cin>>x;
        for (int j : prime)
        {
            if(j*j>x)break;
            if(x%j)continue;
            int cnt=0;
            while(x%j==0){
                x/=j;
                cnt++;
            }
            mp[i][j]=cnt;
            s[j].insert(cnt);
        }if(x>1)s[x].insert(1),mp[i][x]=1;
    }ll g=1;
    for (int i : prime)
    {
        if(int(s[i].size())==n){
            g=g*ksm((ll)i,(ll)(*s[i].begin()))%mod;
            pre[i]=*s[i].begin();
        }
    }
    while(q--){
        int x,y;
        cin>>x>>y;
        for (int i : prime)
        {
            if(i*i>y)break;
            if(y%i)continue;
            int cnt=0;
            while(y%i==0)y/=i,cnt++;
            if(mp[x].count(i)){
                s[i].erase(s[i].find(mp[x][i]));
            }mp[x][i]+=cnt;
            s[i].insert(mp[x][i]);
            if(int(s[i].size())==n){
                g=g*ksm((ll)i,(ll)(*s[i].begin()-pre[i]))%mod;
                pre[i]=*s[i].begin();
            }
        }if(y>1){
            if(mp[x].count(y)){
                s[y].erase(s[y].find(mp[x][y]));
            }mp[x][y]++;
            s[y].insert(mp[x][y]);
            if(int(s[y].size())==n){
                g=g*ksm((ll)y,(ll)(*s[y].begin()-pre[y]))%mod;
                pre[y]=*s[y].begin();
            }
        }cout<<g<<endl;
    }
    return 0;
}

参考博客:https://www.cnblogs.com/StarRoadTang/p/14494421.html

posted @ 2021-03-08 18:18  !^^!  阅读(92)  评论(0)    收藏  举报