欢迎来到我的算法与代码笔记(建设中)

在这里记录学习之旅,分享编程心得,用二次元的活力激发灵感!

开始阅读

随笔标题一

简要摘要介绍,方便读者快速了解文章主要内容。

随笔标题二

简要摘要介绍,方便读者快速了解文章主要内容。

集合(并查集)

P1621 集合

题目描述

Caima 给你了所有 [a,b] 范围内的整数。一开始每个整数都属于各自的集合。每次你需要选择两个属于不同集合的整数,如果这两个整数拥有大于等于 p 的公共质因数,那么把它们所在的集合合并。

重复如上操作,直到没有可以合并的集合为止。

现在 Caima 想知道,最后有多少个集合。

输入格式

一行,共三个整数 a,b,p,用空格隔开。

输出格式

一个数,表示最终集合的个数。

输入输出样例 #1

输入 #1

10 20 3

输出 #1

7

说明/提示

样例 1 解释

对于样例给定的数据,最后有 {10,20,12,15,18},{13},{14},{16},{17},{19},{11}7 个集合,所以输出应该为 7

数据规模与约定

  • 对于 80% 的数据,1ab103
  • 对于 100 的数据,1ab105,2pb

分析

明显并查集,但是卡了半天(菜),第一次读错题目了,第二次,是细节没把握好,

下面看一下正常思路:首先题目要求素数,那么肯定是要筛选素数的,其次,在[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;
}
posted @   bakul  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示