cf-round706-div2-D/map/multiset/gcd/素数筛

https://codeforces.ml/contest/1493/problem/D   《题目来源》

题目特征:

2e5个位点,2e5以内的数字,2e5的操作并询问。

特点:

2e5以内的数字:数字的质因数情况能够预处理

 

这题我不是很懂,非常不懂。

cf上面的题解看不懂,对着标称学习吧。  https://codeforces.ml/blog/entry/88422     《题解》

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int const maxn = 2e5 + 5, max_val = 2e5 + 5;
ll mod = 1e9 + 7, ans = 1;
int nxt[max_val], n;
multiset <int> cnt[max_val];
map <int, int> cnt_divisor[maxn];

void add(int i, int x) {
    while (x != 1) {
        int div = nxt[x], add = 0;
        while (nxt[x] == div) add++, x = x / nxt[x];

        int lst = cnt_divisor[i][div];
        cnt_divisor[i][div] += add;
        int lst_min = 0;
        if ((int)cnt[div].size() == n) {
            lst_min = (*cnt[div].begin());
        }
        if (lst != 0) {
            cnt[div].erase(cnt[div].find(lst));
        }
        cnt[div].insert(lst + add);
        if ((int)cnt[div].size() == n) {
            for (int j = lst_min + 1; j <= (*cnt[div].begin()); ++j) {
                ans = ans * (ll)div % mod;
            }
        }
    }
}

main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int q, l, x;
    cin >> n >> q;

    for (int i = 2; i < maxn; ++i) {
        if (nxt[i] == 0) {
            nxt[i] = i;
            if (i > 10000) continue;
            for (int j = i * i; j < maxn; j += i) {
                if (nxt[j] == 0) nxt[j] = i;
            }
        }
    }

    for (int i = 1; i <= n; ++i) {
        cin >> x;
        add(i, x);
    }

    for (int i = 1; i <= q; ++i) {
        cin >> l >> x;
        add(l, x);
        cout << ans << '\n';
    }

    return 0;
}
标称

 

大概摸清了几个部分:

一、预处理:由欧拉筛演变

在筛的基础上,给2e5的每个数字预处理出其最小的素因数,记为nxt[i]。

二、把初始状态与询问状态统一处理

初始状态视为无需输出的操作

三、了解一下map与multiset

map   https://www.cnblogs.com/yonglin1998/p/11780828.html

为了获得一个动态大小的二维数组。map<int, int>cnt_divisor[maxn]

multiset   https://blog.csdn.net/sodacoco/article/details/84798621

看做一个自动维护(log n)的序列,st.insert(5), st.begin(), st.end(), st.erase(st.begin()), st.find(5)

四、思路比较简单

对于每个询问,(借用nxt【】)一个质数一个质数地处理因数

先统计贡献了多少个质数k,然后把k存入统计列表,

若满足n个位点在该质因数上都有贡献,则让ans乘其最小个数。

ans递增,每次乘那个质因数即可。

 

posted @ 2021-03-11 16:47  windiest  阅读(34)  评论(0编辑  收藏  举报