题目大意
给出 n ( 1 ≤ n ≤ 2 e 5 ) n(1 \leq n \leq 2e5) n(1≤n≤2e5)个数的序列 a [ ] a[~] a[ ]和 m m m次更新,每次更新可以将 a [ i ] a[i] a[i]乘上 x ( 1 ≤ x ≤ 2 e 5 ) x(1 \leq x \leq 2e5) x(1≤x≤2e5),输出每次更新后这 n n n个数的 g c d gcd gcd。
解题思路
这题咋一看不太难但是细思也不简单。 g c d gcd gcd在质因数分解下的意义为所有的 n n n个数公共质因子的最小幂次相乘,可以预处理最小质因子常数时间复杂度分解质因数。
因为每个数都小于 2 e 5 2e5 2e5,所以仔细思考最坏平均的给每个数的质因数都拉满,最终每个数的质因数种类也不会超过十种,因此内存是够的,既然内存够我们就使用 m u l t i s e t multiset multiset存下每种质因子对应 n n n个数中的个数,仅当 m u l t i s e t multiset multiset的容量为 n n n时才会更新答案;使用 u n o r d e r e d _ m a p unordered\_map unordered_map存下每个数每种因子的对应数量,然后就差不多是模拟题了。
//
// Created by Happig on 2021/3/9.
//
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define ENDL "\n"
#define lowbit(x) (x & (-x))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double dinf = 1e300;
const ll INF = 1e18;
const int Mod = 1e9 + 7;
const int maxn = 2e5 + 10;
ll ans;
int n, num[maxn]; //存每种质因子的数量
multiset<int> ms[maxn]; //存每种质因子在n个数中的所有出现的数目
int prime[maxn / 3], minp[maxn], cnt;
unordered_map<int, int> vis[maxn];
map<int, int> mp;
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a % b);
}
void euler() {
cnt = 0;
for (int i = 1; i < maxn; i++) minp[i] = i;
for (int i = 2; i < maxn; i++) {
if (minp[i] == i) prime[++cnt] = i;
for (int j = 1; j <= cnt && i * prime[j] < maxn; j++) {
minp[i * prime[j]] = prime[j];
if (i % prime[j] == 0) break;
}
}
}
ll qkp(ll x, ll q, ll p) {
ll res = 1;
while (q) {
if (q & 1) res = res * x % p;
x = x * x % p;
q >>= 1;
}
return res;
}
void divide(int idx, int x) {
mp.clear();
while (x > 1) {
mp[minp[x]]++;
x /= minp[x];
}
for (auto i:mp) {
vis[idx][i.first] = i.second, num[i.first]++;
ms[i.first].insert(i.second);
}
}
void cal(int idx, int x) {
mp.clear();
while (x > 1) {
mp[minp[x]]++;
x /= minp[x];
}
for (auto i:mp) {
if (vis[idx][i.first]) {
int pre = *ms[i.first].begin();
auto pos = ms[i.first].lower_bound(vis[idx][i.first]);
ms[i.first].erase(pos);
vis[idx][i.first] += i.second;
ms[i.first].insert(vis[idx][i.first]);
int now = *ms[i.first].begin();
if (num[i.first] == n) ans = ans * qkp(i.first, now - pre, Mod) % Mod;
} else {
vis[idx][i.first] = i.second;
num[i.first]++;
if (num[i.first] == n) {
ms[i.first].insert(i.second);
int now = *ms[i.first].begin();
ans = ans * qkp(i.first, now, Mod) % Mod;
} else ms[i.first].insert(i.second);
}
}
}
int main() {
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int m, pos, x;
cin >> n >> m;
euler();
for (int i = 1; i <= n; i++) {
cin >> x;
divide(i, x);
if (i == 1) ans = x;
else ans = gcd(ans, x);
}
while (m--) {
cin >> pos >> x;
cal(pos, x);
cout << ans << ENDL;
}
return 0;
}