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;
}