题解:P13461 [GCJ 2008 #1B] Number Sets
本题解来自于《挑战程序设计竞赛》。
首先因为这是一个集合合并的问题,所以貌似可以使用并查集求解。如果对区间内的任意两个数查询是否包含不小于
我们注意到 Large 有一个限制条件是
当
typedef long long ll;
int prime[1000000]; // 不超过1000000的第i个的素数
int p; // 素数的个数
// 输入
ll A, B, P;
void solve() {
int len = B - A + 1;
init_union_find(len); // 初始化并查集
for (int i = 0; i < p; i++) {
// 对不小于P的素数进行处理
if (prime[i] >= P) {
// 不小于A的最小的prime[i]的倍数
ll start = (A + prime[i] - 1) / prime[i] * prime[i];
// 不大于B的最大的prime[i]的倍数
ll end = B / prime[i] * prime[i];
for (ll j = start; j <= end; j += prime[i]) {
// start和j属于同一个集合
unite(start - A, j - A);
}
}
}
int res = 0;
for (ll i = A; i <= B; i++) {
// find(i) == i时,i就是并查集的根
// 集合的个数等于根的个数
if (find(i - A) == i - A) res++;
}
printf("%d\n", res);
}