luoguP1621 集合

链接

题目

Caima 给你了所有 [a,b] 范围内的整数。一开始每个整数都属于各自的集合。每次你需要选择两个属于不同集合的整数,如果这两个整数拥有大于等于 pp 的公共质因数,那么把它们所在的集合合并。
重复如上操作,直到没有可以合并的集合为止。
现在 Caima 想知道,最后有多少个集合。

就是一道简单的并查集的问题,我写了好久,错了好多地方……
错误:
1.在判断两个数能否合并的函数中,写了一句if (pri[i]*2 > min(x, y)) break;本来想优化,但是这样就枚举不到小正数了
以后在写优化的时候想想正确性。
2.采用n方枚举a,b 之间的两个数,能否合并,在n == 1000000 的时候会T,并且做了很多重复的合并,参考了题解,采用了枚举质数的方法,每次只合并相邻的两个倍数
3. i 和 t 写反了,以后要细心呐!
4. 使用别人正确的程序进行调试。

代码

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 100010;
int a, b, p,fa[MAXN];

int find(int x)
{
	if (fa[x] != x) return fa[x] = find(fa[x]);
	return fa[x];
}
void unionn(int x, int y)
{
	int xx = find(x); int yy = find(y);
	if (xx != yy) fa[xx] = yy;
}

bool he[MAXN];
int nump, pri[MAXN];
void make_prime(int n)
{
	for (int i = 2; i <= n; i ++)
	{
		if (!he[i]) pri[++nump] = i;
		for (int j = 1; j <= nump && i * pri[j] <= n; j ++)
		{
			he[i*pri[j]] = 1;
			if (i % pri[j] == 0) break;
		}
	}
}

int main()
{
	scanf("%d%d%d",&a,&b,&p);
	for (int i = a; i <= b; i ++)
		fa[i] = i;
	make_prime(b);
	for (int i = 1; i <= nump; i ++)
	{
		if (pri[i] < p) continue;
//		printf("%d ",pri[i]); cout << endl;
		int t = 0;
		while (pri[i] * t < a) t ++;
		while (pri[i]*(t+1) <= b)
		{
			unionn(pri[i]*t, pri[i]*(t+1));
			t ++;
		}
	}
	int ans = 0;
	for (int i = a; i <= b; i ++)
		if (fa[i] == i) ans ++;
	printf("%d",ans);
	return 0;
}
/*
20 100000 6

10 20 3
7
365 952 5
129
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值