传送门:https://codeforces.com/contest/1493/problem/D
题意
给一个长度为n的序列,有q个操作,每次操作会将第i个数乘x,在输出gcd(所有数).
思路
因为每次操作只对一个数操作,而不是区间修改,而且是不是求区间gcd。 即不需要用线段树求区间gcd,可以用可以动态开点维护每个质因子的min值。
$gcd=p_1^{min(k_1,k_2…k_n)}…p_n^{min(k_1,k_2…k_n)}$
本篇题解是利用multiset维护每个质因子的min值。 因为multiset每次操作都是$\log n$,而且mtltiset内部都是有序的,可重复的,简直完美!
定义prime[i][j]表示第i个数字的质因子j的个数。 定义mt[i]表示质因子i的个数的有序序列。 所以当每个数字都有i这个因子时,即: $if(mt[i].size() == n) \;*mt[i].begin()$即为质因子i的最小值贡献。
每次操作一次的时候,先对x质因子分解,然后对每个质因子操作,并维护mt[i]。
所以暴力模拟这个过程即可。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| ##include "bits/stdc++.h" using namespace std;
typedef long long ll;
##define endl "\n" const ll mod = 1e9 + 7;
const int N = 2e5 + 10;
ll quick_pow(ll a, ll b) { ll ans = 1; while(b) { if(b & 1) ans = ans * a % mod; a = a * a % mod; b >>= 1; } return ans % mod; }
bool is_prime[N]; int prime[N];
void init() { for(int i = 2;i < N; i++) { if(!is_prime[i]) { for(int j = 1;i * j < N; j++) { prime[i * j] = i; is_prime[i * j] = 1; } } } }
map<int, int> primes[N]; multiset<int> mt[N];
void solve() { init(); int n, q; cin >> n >> q; for(int i = 1;i <= n; i++) { int x; cin >> x; while(x > 1) { primes[i][prime[x]]++; x /= prime[x]; } for(auto &it : primes[i]) { mt[it.first].insert(it.second); } } ll ans = 1; for(int i = 1;i < N; i++) { if(mt[i].size() == n) { ans = ans * quick_pow(i, *mt[i].begin()) % mod; } } while(q--) { int i, x; cin >> i >> x; map<int, int> cnt; while(x > 1) { cnt[prime[x]]++; x /= prime[x]; } for(auto &it : cnt) { if(primes[i].find(it.first) == primes[i].end()) { primes[i][it.first] = it.second; mt[it.first].insert(it.second); if(mt[it.first].size() == n) { ans = ans * quick_pow(it.first, *mt[it.first].begin()) % mod; } } else { int pre = primes[i][it.first]; int cur = pre + it.second; int premin = *mt[it.first].begin(); mt[it.first].erase(mt[it.first].find(pre)); mt[it.first].insert(cur); int nowmin = *mt[it.first].begin(); primes[i][it.first] = cur; if(mt[it.first].size() == n) { ans = ans * quick_pow(it.first, nowmin - premin) % mod; } } } cout << ans << endl; } }
signed main() { solve(); }
|
本文作者:jujimeizuo
本文地址: https://blog.jujimeizuo.cn/2021/03/07/codeforces-round-705-div2-d-g/
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0 协议。转载请注明出处!