LCM on Whiteboard(质因数分解,最小公倍数)

题意

给定\(N\)个整数\(a_1, a_2, \dots, a_n\)

每个整数以质因数分解的形式给出,假设整数\(a_i\)\(m_i\)个不同的质因数,分别为\(p_{i, 1}, p_{i, 2}, \dots, p_{i, m_i}\),它们的指数分别为\(e_{i, 1}, e_{i, 2}, \dots, e_{i, m_i}\)

你现在需要选择其中一个整数,将其替换为\(1\)

问替换后所有整数的最小公倍数取值有多少种可能。

数据范围

\(1 \leq N \leq 2 \times 10^5\)
\(\sum m_i \leq 2 \times 10^5, 1 \leq m_i\)
\(2 \leq p_{i, 1} < p_{i, 2} < \dots < p_{i, m_i} \leq 10^9\)
\(1 \leq e_{i, j} \leq 10^9\)

思路

首先考虑最小公倍数如何求。对于每一个质因子\(p\),其指数都选择出现过的最大值。

然后我们考虑每个元素,如果将其替换为\(1\),那么对最小公倍数有什么影响。考虑元素的每一个质因子及其指数,只有指数等于最大值,并且最大值唯一,那么这个元素才会对最小公倍数产生影响。

注意,只要某个元素能对最小公倍数产生影响,那么将这个元素替换为\(1\)后的最小公倍数唯一。若不然,某个质因子就有两个最大值了,矛盾。

因此我们只需要统计一下每个元素是否能对最小公倍数产生影响即可。注意,如果存在一个元素不能对最小公倍数产生影响,那么答案需要加\(1\)

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>

using namespace std;

typedef pair<int, int> pii;

const int N = 200010;

int n;
map<int, int> mx, smx;
vector<pii> a[N];

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++) {
        int k;
        scanf("%d", &k);
        for(int j = 1; j <= k; j ++) {
            int x, m;
            scanf("%d%d", &x, &m);
            a[i].push_back({x, m});
            if(m > mx[x]) smx[x] = mx[x], mx[x] = m;
            else if(m > smx[x]) smx[x] = m;
        }
    }
    int ans = 0;
    bool flag = false;
    for(int i = 1; i <= n; i ++) {
        bool ok = false;
        for(auto p : a[i]) {
            int x = p.first, m = p.second;
            if(m == mx[x] && smx[x] < mx[x]) {
                ans ++;
                ok = true;
                break;
            }
        }
        if(!ok) flag = true;
    }
    ans += flag;
    printf("%d\n", ans);
    return 0;
}
posted @ 2022-07-13 18:04  pbc的成长之路  阅读(55)  评论(0)    收藏  举报