Codeforces Round 837题解(A、B、C)

A. Hossam and Combinatorics

|aiaj|最大的就是最大值和最小值,注意要开long long

int n;
int a[N];
 
void solve() {
    cin >> n;
    int min_v = INF, max_v = 0;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i];
        min_v = min(min_v, a[i]);
        max_v = max(max_v, a[i]);
    }
    int cnt_min = 0, cnt_max = 0;
    if (min_v == max_v) {
        cout << n * (n - 1) << '\n';
        return;
    }
    for (int i = 1; i <= n; i ++) {
        if (a[i] == min_v) cnt_min ++;
        if (a[i] == max_v) cnt_max ++;
    }
    cout << cnt_min * cnt_max * 2 << '\n';
}

B. Hossam and Friends

考虑对每一个l,有那些r满足[l,r]中的朋友都互相认识。

设共有m各互相不认识的对(l,r),则所有小于l当前枚举到的i(l,r)对中最小的r的下标都可以作为当前ir

那么我们开个优先队列维护即可。

 
int n, m;
vector<int> bag[N];
priority_queue<PII, vector<PII>, greater<>> pq;
 
void solve() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) bag[i].clear();
    while (!pq.empty()) pq.pop();
    for (int i = 1; i <= m; i ++) {
        int l, r;
        cin >> l >> r;
        if (l > r) swap(l, r);
        bag[l].push_back(r);
    }
    int ans = 0;
    for (int i = n; i >= 1; i --) {
        for (auto j : bag[i]) pq.push({j, i});
        if (pq.empty()) {
            ans += n - i + 1;
            continue;
        }
        ans += pq.top().first - i;
    }
    cout << ans << '\n';
}

C. Hossam and Trainees

如果x可以同时整除a[i]a[j],那么x的一个质因子p就也可以整除a[i]a[j]。一种想法是枚举1e9的的所有质数,判断是否有一个质数可以同时整除a[i]a[j],但是1e9的质数的数量是5.08e7,就算打表,综合起来的时间复杂度也不够用。

考虑对每个数分解质因数,那么如果a[i]a[j]分解质因数的质因子序列有重合的话,就说明a[i]a[j]可以被这两个重合的质因子整除。直接这样做的时间复杂度是O(n1e9),且质因子的跨度太大,开桶难以存下。

我们可以先预处理出1e9的所有质数,这样分解每个a[i]的质因数的时间复杂度可以优化到O(1e9log1e9)。然后由于n最多只会有一个>n的质因数,所以>a[i]的质因数可以用map来存,a[i]的质因数用普通的桶来存即可。

int primes[N], cnt, st[N];
int a[N];
int n;
int cnt_prime[N];
map<int, int> mp;

void getPrimes(int n) {
    for (int i = 2; i <= n; i ++) {
        if (!st[i]) primes[cnt++] = i;
        for (int j = 0; primes[j] <= n / i; j ++) {
            st[primes[j] * i] = 1;
            if (i % primes[j] == 0) break;
        }
    }
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i];
    }
    int flag = 0;
    mp.clear();
    memset(cnt_prime, 0, (cnt + 2) * sizeof(int));
    for (int i = 1; i <= n; i ++) {
        for (int j = 0; j < cnt && primes[j] <= a[i]; j ++) {
            if (a[i] % primes[j] == 0) {
                cnt_prime[j] ++;
                while (a[i] % primes[j] == 0) a[i] /= primes[j];
            }
        }
        if (a[i] > 1) {
            if (mp[a[i]]) {
                flag = 1;
                break;
            }
            mp[a[i]] = 1;
        }
    }
    for (int i = 0; i < cnt; i ++) {
        if (cnt_prime[i] > 1) {
            flag = 1;
            break;
        }
    }
    cout << (flag ? "YES" : "NO") << '\n';
}

bool Med;
signed main() {
    fprintf(stderr, "%.3lf MB\n", (&Med - &Mbe) / 1048576.0);
    // setIO();
    int T = 1;
    cin >> T;
    getPrimes(3.4e4);
    while (T --) solve();
    cerr << 1e3 * clock() / CLOCKS_PER_SEC << " ms\n";
    return 0;
}
posted @   lightmon  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示