洛谷P1621-集合

Problem 洛谷P1621-集合

Accept:496  Submit: 1.4k

Time Limit: 1000 mSec    Memory Limit : 128MB

洛谷P1621-集合 Problem Description

现在给你一些连续的整数,它们是从A到B的整数。一开始每个整数都属于各自的集合,然后你需要进行一下的操作:

每次选择两个属于不同集合的整数,如果这两个整数拥有大于等于P的公共质因数,那么把它们所在的集合合并。

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

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

洛谷P1621-集合 Input

一行,三个整数A,B,P。

【数据规模】

A≤B≤100000;

2≤P≤B。

洛谷P1621-集合 Output

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

洛谷P1621-集合 Sample Input

10 20 3

洛谷P1621-集合 Sample output

7

题目链接:https://www.luogu.org/problemnew/show/P1621

题解:水题,之所以记录一下是因为感觉自己在做这道题的时候才感觉真的弄明白了欧拉筛的证明,以前会证明,但是感觉是只是机械化的证明,没有自己的理解。

我认为证明中最精华的一句话是,在i%prime[j] == 0,之前,prime[j]均为i*prime[j]的最小素因子,这个结论很显然,但是起到了决定性作用......

筛完素数就是简单的并查集。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std; const int maxn = +;
bool is_prime[maxn];
int tot,prime[maxn];
int pre[maxn];
int a,b,p; void get_Prime(){
memset(is_prime,true,sizeof(is_prime));
is_prime[] = is_prime[] = false;
tot = ;
for(int i = ;i < maxn-;i++){
if(is_prime[i]) prime[tot++] = i;
for(int j = ;j<tot && prime[j]<=maxn/i;j++){
is_prime[i*prime[j]] = false;
if(i%prime[j] == ) break;
}
}
} int findn(int x){
return x == pre[x] ? x : pre[x] = findn(pre[x]);
} void merge_node(int x,int y){
int fx = findn(x),fy = findn(y);
if(fx != fy){
pre[fx] = fy;
}
} int main()
{
//freopen("input.txt","r",stdin);
get_Prime();
scanf("%d%d%d",&a,&b,&p);
for(int i = a;i <= b;i++){
pre[i] = i;
}
int pos = lower_bound(prime,prime+tot,p)-prime;
for(int i = pos;prime[i] <= b;i++){
for(int j = ;j*prime[i] <= b;j++){
if((j-)*prime[i] < a) continue;
merge_node((j-)*prime[i],j*prime[i]);
}
}
int cnt = ;
for(int i = a;i <= b;i++){
if(pre[i] == i) cnt++;
}
printf("%d\n",cnt);
return ;
}
上一篇:评点SAP HR功能及人力资源管理软件


下一篇:C# 获取程序运行目录