F - GCD of an Array
F - GCD of an Array
https://codeforces.ml/problemset/problem/1493/D
题意
首先给定长度为n的初始数组 有q次操作 每次操作输入 i v 代表给下标为i的数乘上v 每次询问求当前数组中的数的最大公因子(gcd)
思路
要求gcd 那肯定要分解质因子 可以用普通的素数筛也可以用欧拉筛(欧拉筛更快一点)
每个位置上的数的共同质因数乘起来就是gcd 我们可以确定gcd肯定是一直增加的
对于每个位置我们可以用一个二维mp 来记录 mp[p][i]就代表位置是p中质因数是i的个数
用multiset<>set[i]来储存素数为i的在不同位置当前出现过几次 当每个位置都有质因数i的时候 那就要对答案贡献 其中最小个数质数i
但是贡献完后无法将每个set都减去 下次质因数i的不同个数又到达了n就无法再操作了 那我们可以先除去更新前最小值i set中删去那个位置的值 然后更新mp 再插进set[i]里用于下次更新 取更新后set[i]的第一个值就是再乘以几个i(后面的个数就包括了前面更新的个数mp是一直增加的) 这里乘几个i和除几个i用快速幂和逆元表示
每次要判断mp[p]i中是否有值 没有值可以直接插入 有值的话要判断是否已经达到了n 达到了就要进行贡献处理
之所以用multiset是因为其可以重复且键值排序
#include<bits/stdc++.h>
#include<unordered_map>
#define ll long long
#define ull unsigned long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const ll inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-4;
const ll N = 2e5 + 5;
const int mod = 1e9 + 7;
ll n, q;
int isPrime[N];
vector<int> prime;
ll tot, ans = 1;
unordered_map<ll, ll> mp[N];
multiset<ll >st[N];
//快速幂
ll ksm(ll base, ll pow) {
ll ans = 1;
while (pow) {
if (pow & 1) ans = ans * base % mod;
base = base * base % mod;
pow >>= 1;
}
return ans;
}
void work(ll t, ll p, ll cnt1) {
if (mp[p].count(t)) {//出现过
if (st[t].size() == n) {//达到了n个先除以贡献
ll res = ksm(t, *st[t].begin());
ans = (ans % mod * ksm(res, mod - 2)) % mod;
}//更新 先去掉更新前的 再更新后插入更新了的
st[t].erase(st[t].find(mp[p][t]));//st[i].find(mp[p][t])返回迭代器
mp[p][t] += cnt1;
st[t].insert(mp[p][t]);
}
else {//没有出现过 直接加
mp[p][t] = cnt1;
st[t].insert(mp[p][t]);
}//如果更新后再次满了 那就进行乘的贡献
if (st[t].size() == n) {
ans = (ans % mod * ksm(t, *st[t].begin())) % mod;
}
}
void getp2(ll x, ll p) {
//找质因子
for (int i = 2; i <= x / i; ++i) {
if (!(x % i)) {
int cnt1 = 0;
while (x % i == 0) {
x /= i;
++cnt1;
}
work(i, p, cnt1);
}
}
if (x > 1) {
work(x, p, 1);
}
}
void solve() {
cin >> n >> q;
for (int i = 1, x; i <= n; i++) {
cin >> x;
getp2(x, i);
}
ll p, x;
for (int i = 1; i <= q; i++) {
cin >> p >> x;
getp2(x, p);
cout << ans << "\n";
}
}
signed main() {
IOS;
//getprime();
int t = 1;
//cin >> t;
while (t--) {
solve();
}
}