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

题目链接:D. GCD of an Array
思路:纯纯的数据结构题目,一看数据范围\(2e5\)很显然是维护每一个质数的最小的个数,\(2e5\)内的素数个数不超过\(2e4\),所以我们对于每一个素数用一个map来存对于\(a_i\)的该素因子的个数,然后用另外一个map存反(其实可以用multiset代替),另一个我们只需要知道个数,然后求最小值操作也是用存反的map完成的,因为内部是用key进行排序的。
\(Code:\)

#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define lowbit(x) (x&(-x))
#define ch() getchar()
#define pc(x) putchar(x)
using namespace std;

template<typename T>void read(T&x)
{
    static char c;
    static int f;
    for(c=ch(),f=1; c<'0'||c>'9'; c=ch())if(c=='-')f=-f;
    for(x=0; c>='0'&&c<='9'; c=ch())x=x*10+(c&15);
    x*=f;
}
template<typename T>void write(T x)
{
    static char q[65];
    int cnt=0;
    if(x<0)pc('-'),x=-x;
    q[++cnt]=x%10,x/=10;
    while(x)
        q[++cnt]=x%10,x/=10;
    while(cnt)pc(q[cnt--]+'0');
}
const int N = 2e5+10;
const ll mod = 1e9+7;
const int M = 2e4+10;
int prime[N];
map<int,int>S[M],P[M];
int tot = 0;
bool st[N];
int n,q,a[N];
int up[N];
long long q_pow(long long base, long long power) {
    long long result = 1;
    while (power > 0) {
        if (power & 1) {
            result = result * base ;
        }
        power >>= 1;
        base = (base * base) ;
    }
    return result;
}
void _prime()
{
    rep(i,2,2e5)
    {
        if(st[i] == false)
        {
            prime[++tot] = i;
            up[i] = prime[tot];
            if(i>1e4)continue;
            for(int j=i*i; j<=2e5; j+=i)
            {
                st[j] = true;
            }
        }
    }
}
void init(int x,int idx)
{
    int id = 1;
    while(prime[id] * prime[id] <= x)
    {
        int cnt = 0;
        while(x%prime[id] == 0)x/=prime[id],cnt++;
        if(cnt)
        {
            S[id][idx] += cnt;//作访问用
            P[id][cnt]++;
        }
        id++;
    }
    if(x == 1)return ;
    int k = lower_bound(prime+1,prime+1+tot,x)-prime;
    S[k][idx] += 1;
    P[k][1]++;
}
int sum;
void doit(int cnt,int id,int idx)
{
    if(!cnt)return ;
    bool flag = true;
    if((int)S[id].size() != n)flag = 0;
    int l = S[id][idx];
    int r = l + cnt;
    auto it=P[id].begin();
    pair<int,int>a1 = *it;
    int ans = a1.first;
    if(flag == false)ans = 0;
    S[id][idx] = r;
    if(l!=0)
        P[id][l]--;
    P[id][r]++;
    if(P[id][l] == 0)
    {   auto s = P[id].find(l);
        //printf("%d\n",*s.first);
        P[id].erase(s);
    }
    //printf("%d %d %d %d %d\n",(int)S[id].size(),prime[id],l,r,ans);
    if((int)S[id].size()!=n)
    {
        return ;
    }
    //auto k=S[id].lower_bound(S[id].begin(),S[id].end(),1)-S[id].begin();
    auto k = P[id].begin();
    auto c = *k;//printf("%d %d\n",c.first,c.second);
    if(c.first == ans)return;
    sum *= (ll)q_pow(prime[id],c.first-ans);
   // printf("%d\n",prime[id]);
}
int add(int x,int idx)
{
    int id = 1;
    sum = 1;
    while(prime[id] * prime[id] <= x)
    {
        int cnt = 0;
        while(x%prime[id] == 0)x/=prime[id],cnt++;
        doit(cnt,id,idx);
        id++;
    }
    if(x == 1)return sum;
    auto k = lower_bound(prime+1,prime+1+tot,x)-prime;
    doit(1,k,idx);
    return sum ;
}
int _;
void solve()
{
    _prime();
    read(n);
    read(q);
    int sum;
    rep(i,1,n)
    {
        read(a[i]);
        init(a[i],i);
        if(i == 1)sum = a[i];
        else sum = __gcd(sum,a[i]);
    }
    ll now = sum*1ll;
    while(q--)
    {
        int idx,v;
        read(idx);
        read(v);
        now *=add(v,idx)%mod;
        now %=mod;
        write(now);pc('\n');
    }

}
signed main()
{
    solve();
    return 0;
}



上一篇:三次函数


下一篇:备忘录