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
    评论
根据引用\[1\],对于问题P7114 \[NOIP2020\] 字符串匹配,我们可以使用枚举的方法来确定AB的可能情况,并进一步确定C的可能情况。假设枚举的AB是前缀iii,那么C只可能是后缀i+1i+1i+1,以及后缀i+1i+1i+1去掉前面的若干AB后得到的后缀。我们可以预处理出每个前缀和后缀中出现奇数次字符的个数。根据观察,对于AB循环奇数次和偶数次来说,它们的C的上述值分别相同。因此,我们可以分别考虑AB循环奇数次和偶数次的情况,从前往后记录当前有多少个前缀的出现奇数次字符个数为i。在询问时,我们可以直接暴力询问前缀和,总的复杂度大约是O(26n)。如果使用树状数组,复杂度可以优化到O(nlog26)。 根据引用\[2\],这个问题与周期串有关。朴素的KMP算法只能求出一个周期串的最小循环节,对于本题来说是不够的。我们需要知道对于一个AB来说,它最多能往后循环多少次。虽然可以使用二分法来解决,但是复杂度较高。 根据引用\[3\],我们可以优化复杂度。由于postodd每次只变化1,我们可以记录从i变化到i+1或者i-1时,A串满足条件的个数的变化情况。对于奇数k,没有什么特殊的情况。对于偶数k,我们注意到C串的奇偶性与整串一致,因此可以直接使用整串的奇偶性即可。 综上所述,对于问题P7114 \[NOIP2020\] 字符串匹配,我们可以使用枚举的方法来确定AB的可能情况,并根据不同情况进行处理。可以使用树状数组来优化复杂度。 #### 引用[.reference_title] - *1* *2* [【LuoguP7114】[NOIP2020] 字符串匹配 (扩展KMP算法)](https://blog.csdn.net/element_hero/article/details/113036427)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [P7114 [NOIP2020] 字符串匹配](https://blog.csdn.net/beneath_haruhi/article/details/120634165)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值