Codeforces Round #705 (Div. 2) D题-GCD of an Array

题意:

给出一个长度为 n n n 数组,和 q q q 次操作,每次操作将 第 i i i 位的数乘上 x x x ,然后输出全部数的 g c d gcd gcd

题解:

可以将 g c d gcd gcd 考虑成每个质数的贡献,即所有数分解后质数的最低次幂。

先预处理出n个数分解后质数有多少次幂,用 m a p map map 存一下, m p [ i ] [ j ] mp[i][j] mp[i][j] 表示第 i i i 个数分解后质数 j j j 有多少次幂。

然后再用 m u l t i s e t multiset multiset 存每个质数分别在 1 1 1 n n n 里面出现了几次,即 s e t [ i ] set[i] set[i] 里面存了这n个数分解后 i i i 有多少次幂。

这样 s e t set set 里面的首元素就是对答案的贡献次幂。

然后再考虑 q q q 个操作:

也是先对 x x x 进行质因数分解,然后修改第 i i i 个数的质数的次幂和 m u l t i s e t multiset multiset 里面的值,再考虑对 g c d gcd gcd 的贡献即可。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=2e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
int prime[MAXN],cnt;
int isprime[MAXN];
multiset<int>p[MAXN];
map<int,int>mp[MAXN];
int a[MAXN];
void getprime(int n)
{
    
    
    for(ll i=2;i<=n;i++)
    {
    
    
        if(!isprime[i])
        {
    
    
            prime[++cnt]=i;
            isprime[i]=i;
        }
        for(int j=1;j<=cnt&&i*prime[j]<=n;j++)
        {
    
    
            isprime[i*prime[j]]=prime[j];
            if(i%prime[j]==0) break;
        }
    }
}
ll qpow(ll x,ll y)
{
    
    
    ll res=1;
    while(y)
    {
    
    
        if(y&1) res=res*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return res;
}
int main()
{
    
    
    getprime(2e5);
    int n,q;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
    {
    
    
        scanf("%d",&a[i]);
        int temp=a[i];
        while(temp!=1)
        {
    
    
            mp[i][isprime[temp]]++;
            temp/=isprime[temp];
        }
        temp=a[i];
        int pre=isprime[temp];
        while(temp!=1)
        {
    
    
            if(isprime[temp]!=pre)
            {
    
    
                p[pre].insert(mp[i][pre]);
            }
            pre=isprime[temp];
            temp/=isprime[temp];
        }
        if(pre)
        {
    
    
            p[pre].insert(mp[i][pre]);
        }
    }
    ll ans=1;
    for(int i=1;i<=cnt;i++)
    {
    
    
        if(p[prime[i]].size()==n)
        {
    
    
            ans=ans*(qpow(prime[i],*p[prime[i]].begin()))%mod;
        }
    }
    while(q--)
    {
    
    
        int op,x;
        scanf("%d%d",&op,&x);
        int temp=x;
        int pre=isprime[temp];
        int cnt=0;
        while(temp!=1)
        {
    
    
            if(pre!=isprime[temp])
            {
    
    
                if(mp[op].count(pre)==0)
                {
    
    
                    mp[op][pre]+=cnt;
                    p[pre].insert(cnt);
                    if(p[pre].size()==n)
                    {
    
    
                        ans=ans*(qpow(pre,*p[pre].begin()))%mod;
                    }
                }
                else
                {
    
    
                    int last=*p[pre].begin();
                    p[pre].erase(p[pre].lower_bound(mp[op][pre]));
                    mp[op][pre]+=cnt;
                    p[pre].insert(mp[op][pre]);
                    int now=*p[pre].begin();
                    if(p[pre].size()==n&&now>last)
                    {
    
    
                        ans=ans*(qpow(pre,now-last))%mod;
                    }
                }
                cnt=0;
            }
            pre=isprime[temp];
            cnt++;
            temp/=isprime[temp];
        }
        if(pre)
        {
    
    
            if(mp[op].count(pre)==0)
            {
    
    
                mp[op][pre]+=cnt;
                p[pre].insert(cnt);
                if(p[pre].size()==n)
                {
    
    
                    ans=ans*(qpow(pre,*p[pre].begin()))%mod;
                }
            }
            else
            {
    
    
                int last=*p[pre].begin();
                p[pre].erase(p[pre].lower_bound(mp[op][pre]));
                mp[op][pre]+=cnt;
                p[pre].insert(mp[op][pre]);
                int now=*p[pre].begin();
                if(p[pre].size()==n&&now>last)
                {
    
    
                    ans=ans*(qpow(pre,now-last))%mod;
                }
            }
        }
        printf("%lld\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_45755679/article/details/114496223