//如果对并查集不懂的,先把并查集搞懂再看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
int fa[100005],mark[100005];
//很常规的并查集查找函数
int find(int x){
if(x!=fa[x])fa[x]=find(fa[x]);
return fa[x];
}
bool f(int x){
if(x==2)return true;
if(x%2==0||x==1)return false;
for(int i=3;i<=sqrt(x);i+=2){
if(x%i==0)return false;
}
return true;
}
void solve(){
int a,b,p;
cin>>a>>b>>p;
for(int i=1;i<=b;i++)fa[i]=i;//为啥是从1到b呢?,因为质因数可能小于a
int ans=b-a+1;//这里是有技巧的,实际上要开一个桶去遍历一遍查找集合个数
//但是最多有b-a+1个集合,所以每合并两个集合ans--,也是可以的
for(int i=p;i<=b;i++){
if(mark[i])continue;//减少工作量,因为i为质数,所以i的倍数都不是质数
if(f(i)){//f()是质数判断函数
for(int j=1;j*i<=b;j++){
if(j*i<a)continue;//必须保证j*i>=a&&j*i<=b
mark[j*i]=1;//把质数i的倍数标记为非质数
int x=find(i),c=find(j*i);
//并查集的联合操作
if(x!=c){
fa[x]=c;
if(x>=a&&x<=b&&j*i>=a&&j*i<=b)ans--;
//为啥ans--要加条件,因为当(3,12)联合时3是小于a的
//3和12联合集合数并没有改变
}
}
}
}
cout<<ans;
return ;
}
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _;
//cin>>_;
_=1;
while(_--){
solve();
}
return 0;
}
洛谷P1621 集合
最新推荐文章于 2024-07-06 15:43:38 发布
![](https://img-home.csdnimg.cn/images/20240611030827.png)