最新文章
这里会显示最新的几篇文章摘要。
记录生活,分享知识,与你一起成长。
这里会显示最新的几篇文章摘要。
Caima 给你了所有 \([a,b]\) 范围内的整数。一开始每个整数都属于各自的集合。每次你需要选择两个属于不同集合的整数,如果这两个整数拥有大于等于 \(p\) 的公共质因数,那么把它们所在的集合合并。
重复如上操作,直到没有可以合并的集合为止。
现在 Caima 想知道,最后有多少个集合。
一行,共三个整数 \(a,b,p\),用空格隔开。
一个数,表示最终集合的个数。
10 20 3
7
对于样例给定的数据,最后有 \(\{10,20,12,15,18\},\{13\},\{14\},\{16\},\{17\},\{19\},\{11\}\) 共 \(7\) 个集合,所以输出应该为 \(7\)。
明显并查集,但是卡了半天(菜),第一次读错题目了,第二次,是细节没把握好,
下面看一下正常思路:首先题目要求素数,那么肯定是要筛选素数的,其次,在[a, b]看哪些是还有相同的大于p的素因子的,
这个可以用筛选素数的思路,从p开始的素数,筛选p的倍数为一个集合,
最后检查有多少的根节点就可以了
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int fa[N];
inline void init(int n) {
for (int i = 1; i <= n; ++i) fa[i] = i;
}
int finds(int x) {
return fa[x] == x ? x : fa[x] = finds(fa[x]);
}
inline void mergeSet(int a, int b) {
if (finds(a) != finds(b)) fa[finds(a)] = finds(b);
return;
}
bitset<N> pq; // pq[x] == false 表示 x 是质数,true 表示合数
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
// 筛法:pq[i] = false 表示 i 暂时是质数,最终若 pq[i] = true 表示 i 为合数
pq[0] = pq[1] = true;
for (int i = 2; i < 20; ++i) {
//cout << i << endl;
if (!pq[i]) {//cout << i << endl;
for (long long j = 1LL * i * i; j < N; j += i) {
pq[j] = true;
}
}
}
int n,m,p;
cin >> n >> m >> p;
init(m);
for (int i =p;i <= m;++i)
if (!pq[i])
for (int j = i+i;j <= m;j += i)
mergeSet(i,j);
int ans = 0;
for (int i = n;i <= m;++i)
if(fa[i] == i) ans++;
cout << ans;
}