记录编号 618447 评测结果 AAAAAAAAAA
题目名称 4467.NOIP-T1-难度 最终得分 100
用户昵称 Gravatarxuyuqing 是否通过 通过
代码语言 C++ 运行时间 1.360 s
提交时间 2026-09-03 19:09:21 内存使用 30.83 MiB
显示代码纯文本

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

using namespace std;

const int N = 2114514;

bool isnt_prime[N];
int prime_divide[N];
int prime_divide_size[N];

void init () {
    isnt_prime[1] = true;
    for (int i = 1; i < N; i++) {
        prime_divide[i] = 1;
    }
    for (int i = 2; i < N; i++) {
        if (isnt_prime[i]) {
            continue;
        }
        
        prime_divide[i] = i;
        prime_divide_size[i] = 1;
        
        for (int j = i + i; j < N; j += i) {
            isnt_prime[j] = true;
            prime_divide[j] *= i;
            prime_divide_size[j]++;
        }
    }
}

int t;
int l;
int r;
int res;

bool vis[N];
int set_size[N];

void has_prime_solution () {
    memset (vis, 0, sizeof (vis));
    memset (set_size, 0, sizeof (set_size));
    
    for (int i = l; i <= r; i++) {
        set_size[prime_divide[i]]++;
    }
            
    for (int i = 2; i <= r; i++) {
        if (vis[i] || !set_size[i]) {
            continue;
        }
        
        res += set_size[i] * prime_divide_size[i] + 1;
        vis[i] = true;
        
        for (int j = i + i; j <= r; j += i) {
            if (vis[j] || !set_size[j]) {
                continue;
            }
            
            res += set_size[j] * prime_divide_size[j];
            vis[j] = true;
        }
    }
    
    res -= 2;
}

int dad[N];
int union_size[N];

int find (int id) {
    if (dad[id] == id) {
        return id;
    }
    dad[id] = find (dad[id]);
    return dad[id];
}

void merge (int one, int two) {
    one = find (one);
    two = find (two);
    
    if (one == two) {
        return;
    }
    
    if (union_size[one] > union_size[two]) {
        dad[two] = one;
        union_size[one] += union_size[two];
    }
    else {
        dad[one] = two;
        union_size[two] += union_size[one];
    }
}

bool same (int one, int two) {
    return find (one) == find (two);
}

int gcd (int one, int two) {
    if (two == 0) {
        return one;
    }
    return gcd (two, one % two);
} 

void hasnt_prime_solution () {
    for (int i = l; i <= r; i++) {
        dad[i] = i;
        union_size[i] = 1;
    }
    
    vector<pair<int, pair<int, int> > > graph;
    
    for (int i = l; i <= r; i++) {
        for (int j = i + 1; j <= r; j++) {
            graph.emplace_back(prime_divide_size[i] + prime_divide_size[j] - prime_divide_size[gcd (i, j)], make_pair (i, j));
        }
    }
    
    sort (graph.begin(), graph.end());
    
    for (int i = 0, cc = 0; i < graph.size(); i++) {
        int w = graph[i].first;
        int one = graph[i].second.first;
        int two = graph[i].second.second;
        
        if (same (one, two)) {
            continue;
        }
        
        merge (one, two);
        res += w;
        
        cc++;
        if (cc == (r - l + 1) - 1) {
            break;
        }
    }
}

int main () {
    
    freopen ("noipt.in", "r", stdin);
    freopen ("noipt.out", "w", stdout);
    
    cin >> t;
    init ();
    for (int index = 1; index <= t; index++) {
        cin >> l >> r;
        res = 0;
        
        if (l == 1) {
            for (int i = 2; i <= r; i++) {
                res += prime_divide_size[i];
            }
        }
        else {
            bool has_prime = false;
            for (int i = l; i <= r; i++) {
                if (!isnt_prime[i]) {
                    has_prime = true;
                    break;
                }
            }
                
            if (has_prime) {
                has_prime_solution ();
            }
            else {
                hasnt_prime_solution ();
            }
        }
        
        cout << res << endl;
    }
    
    return 0;
}