集合(并查集)
P1621 集合
题目描述
Caima 给你了所有
重复如上操作,直到没有可以合并的集合为止。
现在 Caima 想知道,最后有多少个集合。
输入格式
一行,共三个整数
输出格式
一个数,表示最终集合的个数。
输入输出样例 #1
输入 #1
10 20 3
输出 #1
7
说明/提示
样例 1 解释
对于样例给定的数据,最后有
数据规模与约定
- 对于
的数据, 。 - 对于
的数据, 。
分析
明显并查集,但是卡了半天(菜),第一次读错题目了,第二次,是细节没把握好,
下面看一下正常思路:首先题目要求素数,那么肯定是要筛选素数的,其次,在[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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现