Codeforces 1493D. GCD of an Array

题目链接

题目大意: 给出你n个数,m次操作,让你求操作后n个数的gcd


思路: 因为我们要求gcd。很容易想到我们需要唯一分解这n个数,找到他们公共的部分,乘积就是要求的gcd,重点难点是我们每次要添加更新一个数的因子,所以公共部分可能会改变,也可能不改变。 这就需要我们维护,这个公共部分,我们先把公共部分提取出来做贡献,然后判断加入之后是否构成一个n个数都有的部分,所以我们需要维护一个含插入,删除最小值的数据结构。我就想到这个地方,看被人的博客用的都是multiset。感兴趣的可以去学一下,其实还挺好的。

简单的说下过程:首先对每个数进行唯一分解,分解出来的数让他找到对应的贡献,(就是进入insert)

  1. 如果这个数原本数就有,那么需要更新这个数(如果前面乘过这个最小贡献就需要把这个除下来转化成逆元),更新这个数,如果n个数都有更新。
  2. 如果这个数原本没有,那么直接更新就行,直接判断是否n个数都有,都有这做出贡献乘上即可。
#include <set>
#include <map>
#include <queue>
#include <string>
#include<iostream>
#include<stdio.h>
#include<string.h>
#include <algorithm>
#include <math.h>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
typedef pair<ll,ll> pii;
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mem(a,x) memset(a,x,sizeof(a))
#define debug(x) cout << #x << ": " << x << endl;
#define rep(i,n) for(int i=0;i<(n);++i)
#define repi(i,a,b) for(int i=int(a);i<=(b);++i)
#define repr(i,b,a) for(int i=int(b);i>=(a);--i)
const int maxn=2e5+10;
#define inf 0x3f3f3f3f
#define sf scanf
#define pf printf
const int mod=1e9+7;
const int MOD=1e9+7;

inline int read() {
    
    
    int x=0;
    bool t=false;
    char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
ll n,m,d;
ll a[maxn];
multiset<ll> s[maxn];
map<ll,ll> mp[maxn];
ll qpow(ll a,ll b) {
    
    
    ll ans=1;
    while(b) {
    
    
        if(b&1) ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}
ll inv(ll x) {
    
    
    return qpow(x,mod-2);
}

void insert(ll k, ll i,ll cnt) {
    
    
    if(mp[k].count(i))    {
    
    
        if(s[i].size()==n) d=d*inv(qpow(i,*s[i].begin()))%mod;
        s[i].erase(s[i].find(mp[k][i]));
        mp[k][i]=mp[k][i]+cnt;
        s[i].insert(mp[k][i]);
        if(s[i].size()==n) d=d*qpow(i,*s[i].begin())%mod;
    } else {
    
    
        mp[k][i]=cnt;
        s[i].insert(mp[k][i]);
        if(s[i].size()==n) d=d*qpow(i,*s[i].begin())%mod;
    }
}
void divide(ll k,ll x) {
    
    
    for(int i=2; i<=x/i; i++) {
    
    
        if(x%i==0) {
    
    
            ll cnt=0;
            while(x%i==0) {
    
    
                x=x/i;
                cnt++;
            }
            insert(k,i,cnt);
        }
    }
    if(x>1)insert(k,x,1);
}

int main() {
    
    
    scanf("%lld%lld",&n,&m);
    d=1;
    for(int i=1; i<=n; i++) {
    
    
        scanf("%lld",&a[i]);
    }
    for(int i=1; i<=n; i++) {
    
    
        divide(i,a[i]);
    }


    while(m--) {
    
    
        ll i,x;
        scanf("%lld%lld",&i,&x);
        divide(i,x);
        printf("%lld\n",d);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45911397/article/details/114662602