题目相关

题目链接

洛谷,https://www.luogu.com.cn/problem/P1621。

MYOJ,http://47.110.135.197/problem.php?id=5342。

题目描述

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。

数据范围

1 ≤ a ≤ b ≤ 10^5, 2 ≤ p ≤ b。

题解报告

题意分析

题意还是比较清晰的,不需要分析了。

看完后,就知道考察并查集的知识点。

解题思路

写出 p 到 b 的所有素数。可以使用欧拉筛,或者最基本的素数判定方法。

逐一遍历这些素数,找出从 a 到 b 之间的倍数,将这些数放在同一个集合中。

从 a 到 b 遍历,查找集合的个数。

样例数据分析

根据输入样例,我们知道 a=10,b=20,p=3。

初始化并查集

我们使用 STL 的 map 来保存数据,这样并查集的初始值为:

map<int, int> ds;
ds[10] = 10;
ds[11] = 11;
ds[12] = 12;
ds[13] = 13;
ds[14] = 14;
ds[15] = 15;
ds[16] = 16;
ds[17] = 17;
ds[18] = 18;
ds[19] = 19;
ds[20] = 20;

p 到 b 的素数

这样,我们可以写出 p 到 b 的素数为:3, 5, 7, 11, 13, 17, 19。下面我们开始遍历素数,合并集合。

3 的倍数

在 [10, 20] 区间中,3 的倍数有:12, 15, 18。将这三个数变成一个集合 {12, 15, 18}。这样并查查集 ds 变成:

ds[10] = 10;
ds[11] = 11;
ds[12] = 12;
ds[13] = 13;
ds[14] = 14;
ds[15] = 12;
ds[16] = 16;
ds[17] = 17;
ds[18] = 12;
ds[19] = 19;
ds[20] = 20;

5 的倍数

在 [10, 20] 区间中,5 的倍数有:10, 15, 20。由于 15 既是 3 的倍数也是 5 的倍数,因此这个集合要上上面的集合合并,成为 {12, 15, 18, 10, 20}。这样并查查集 ds 变成:

ds[10] = 12;
ds[11] = 11;
ds[12] = 12;
ds[13] = 13;
ds[14] = 14;
ds[15] = 12;
ds[16] = 16;
ds[17] = 17;
ds[18] = 12;
ds[19] = 19;
ds[20] = 12;

7 的倍数

在 [10, 20] 区间中,7 的倍数有:14。因此这个集合要上上面的集合合并,成为 {14}。这样并查查集 ds 变成:

ds[10] = 12;
ds[11] = 11;
ds[12] = 12;
ds[13] = 13;
ds[14] = 14;
ds[15] = 12;
ds[16] = 16;
ds[17] = 17;
ds[18] = 12;
ds[19] = 19;
ds[20] = 12;

11 的倍数

在 [10, 20] 区间中,11 的倍数有:11。因此这个集合要上上面的集合合并,成为 {11}。这样并查查集 ds 变成:

ds[10] = 12;
ds[11] = 11;
ds[12] = 12;
ds[13] = 13;
ds[14] = 14;
ds[15] = 12;
ds[16] = 16;
ds[17] = 17;
ds[18] = 12;
ds[19] = 19;
ds[20] = 12;

13 的倍数

在 [10, 20] 区间中,13 的倍数有:13。因此这个集合要上上面的集合合并,成为 {13}。这样并查查集 ds 变成:

ds[10] = 12;
ds[11] = 11;
ds[12] = 12;
ds[13] = 13;
ds[14] = 14;
ds[15] = 12;
ds[16] = 16;
ds[17] = 17;
ds[18] = 12;
ds[19] = 19;
ds[20] = 12;

17 的倍数

在 [10, 20] 区间中,17 的倍数有:17。因此这个集合要上上面的集合合并,成为 {17}。这样并查查集 ds 变成:

ds[10] = 12;
ds[11] = 11;
ds[12] = 12;
ds[13] = 13;
ds[14] = 14;
ds[15] = 12;
ds[16] = 16;
ds[17] = 17;
ds[18] = 12;
ds[19] = 19;
ds[20] = 12;

19 的倍数

在 [10, 20] 区间中,19 的倍数有:19。因此这个集合要上上面的集合合并,成为 {19}。这样并查查集 ds 变成:

ds[10] = 12;
ds[11] = 11;
ds[12] = 12;
ds[13] = 13;
ds[14] = 14;
ds[15] = 12;
ds[16] = 16;
ds[17] = 17;
ds[18] = 12;
ds[19] = 19;
ds[20] = 12;

到这里位置,我们已经完成并集。下面我们开始遍历 [a, b] 查询其中有几个集合。

查询集合数

根据上面的数据,我们知道 ds[i]=i 表示这是一个集合,因此我们可以统计出集合数为:7。

技术细节

可以使用欧拉筛来加速素数判定。

AC 参考代码

//http://47.110.135.197/problem.php?id=5342
//https://www.luogu.com.cn/problem/P1621
//P1621 集合
#include <bits/stdc++.h>using namespace std;map<int, int> ds;
map<int, int> ranks;
vector<int> primes;bool isPrime(int x) {for (int i=2; i*i<=x; i++) {if (0==x%i) {return false;}}return true;
}int find_root(int x) {return x==ds[x]?x:ds[x]=find_root(ds[x]);
}int union_set(int x, int y) {int x_root=find_root(x);int y_root=find_root(y);if (x_root==y_root) {return 0;} else {if (ranks[x_root]>ranks[y_root]) {ds[y_root]=x_root;} else if (ranks[x_root]<ranks[y_root]) {ds[x_root]=y_root;} else {ds[x_root]=y_root;ranks[y_root]++;}return 1;}
}int main() {int a,b,p;cin>>a>>b>>p;//初始化并查集for (int i=a; i<=b; i++) {ds[i]=i;ranks[i]=0;}//列出p到b之间的所有素数for (int i=p; i<=b; i++) {if (true==isPrime(i)) {primes.push_back(i);}}//并集for (int i=0; i<primes.size(); i++) {int st=ceil(1.0*a/primes[i])*primes[i];for (int j=st+primes[i]; j<=b; j+=primes[i]) {union_set(st, j);}}//查询有几个集合int ans=0;for (int i=a; i<=b; i++) {if (ds[i]==i) {ans++;}}cout<<ans<<"\n";return 0;
}

洛谷题解——P1621 集合相关推荐

  1. 洛谷题解——P2814 家谱

    题目相关 题目链接 洛谷,https://www.luogu.com.cn/problem/P2814. MYOJ,http://47.110.135.197/problem.php?id=5344. ...

  2. 洛谷-题解 P2672 【推销员】

    独门思路!链表加优先队列! 这题一望,贪心是跑不掉了,但是我贪心并不好,所以想到了一个复杂一些但思路更保稳的做法 思路: 1 因为是离线操作,所以我们可以倒着求,先求x=n的情况,因为那样直接就知道了 ...

  3. 【洛谷题解】P2433 【深基1-2】小学数学 N 合一

    目录 [深基1-2]小学数学 N 合一 题解 题目描述 输入格式 输出格式 样例 #1 样例输入 #1 样例输出 #1 题目解析 问题 1~5 问题 6~10 问题 10~14 发牢骚 完整代码 谢谢 ...

  4. 洛谷题解——P1873:砍树

    视频讲解可以直接点击这个 B 站链接,https://www.bilibili.com/video/BV1jk4y1k7hq/. 题目相关 题目链接 洛谷,https://www.luogu.com. ...

  5. 洛谷题解——P1024:一元三次方程求解

    视频讲解可以直接点击这个 B 站链接,https://www.bilibili.com/video/BV1qT4y13717/. 题目相关 题目链接 洛谷,https://www.luogu.com. ...

  6. 题解系列009 | 洛谷题解 CF488A 【Giga Tower】

    原题传送门:Giga Tower 一.题意 题目(传送门)给一个绝对值不超过十位的整数,想计算至多加几后会在和数中出现数字 888. 二.分析 看到这道题,我们最容易想到的当然是暴力枚举,但是首先需要 ...

  7. 洛谷 P3906 Geodetic集合 题解

    题目描述 图G是一个无向连通图,没有自环,并且两点之间至多只有一条边.我们定义顶点v,u最短路径就是从v到u经过边最少的路径.所有包含在v-u的最短路径上的顶点被称为v-u的Geodetic顶点,这些 ...

  8. 【洛谷题解】P2356 弹珠游戏

    本人第一篇题解 今天闲着没事,随机跳题,然后看到这题,觉得运气爆棚,计蒜客L2时空复杂度的课后原题,微改. 首先,这题我们可以知道枚举处理就行,注意点: 1.千万要分清每个数组的用途,不要写错!!本蒟 ...

  9. 洛谷 P3906 Geodetic集合

    题目大意: nnn个点mmm条遍的无向图,如果点iii在点uuu到点vvv的最短路径(uuu到vvv的边数最少)上,那么记这些点为集合I(u,v)I(u,v)I(u,v) 有kkk个询问,问集合I(u ...

最新文章

  1. libcurl下载限速编程调研
  2. 名头不小!!VMware vSphere实为VI升级版。
  3. HDU1978 记忆化搜索
  4. COJ 0650 绝世难题(一) 可爱的仙人掌
  5. Dashboard集群
  6. Mysql 启动失败没日志,MySQL Server 5.7将无法启动,并且未填充错误日志
  7. 在DataTable和DataView中查找指定记录
  8. 怎样使用计算机网络,教大家怎样用电脑发出wifi信号,让手机共享!
  9. vb 获取系统声音的电平_专业音响系统中常见问题,看看你懂几个?
  10. 0基础Java自学之路
  11. linux中nmap命令,Linux中nmap命令起什么作用呢?
  12. 清华山维EPS二次开发VBS基础篇
  13. 编译原理(整体理解)
  14. 数据结构与算法学习(第一天)
  15. 433lora手持机|手持数据采集终端|lora模块手持PDA
  16. 【郭东白架构课 模块二:创造价值】17|通用技能(下):架构师如何保障交付与沉淀知识?
  17. 记录一次神奇的大物实验——用模拟法测绘静电场——别人都是打铁~我们打孔~~~
  18. Google60款开源项目
  19. Windows下命令行怎样登录MySQL
  20. 1. Nacos的安装与启动

热门文章

  1. 如何让二维码变得好看2
  2. dede首页php调用会员积分,DEDECMS会员签到加积分的实现方法
  3. oracle ora-00911
  4. AI智能安防视频EasyCVR平台接入国标硬件设备播放视频失败的原因排查与分析
  5. 体恤门店,罗曼林冰淇淋发布疫情地区商户补贴方案
  6. Python 循环语句之 for 和 while 的应用
  7. pdf转换为可编辑的ppt文件的方法
  8. 开启SOC3.0时代,启明星辰集团发布新一代安全管理平台系列产品
  9. npm与包格式化时间的两种方式
  10. 废物利用 iPhone中的报刊杂志变身文件夹(无需越狱无需任何工具)