题解【集合】

原题链接:Link

前言

细节还是有点多的 ...

解题思路

没有用到并查集,而是用了筛。

先用筛法把 \(1\)\(100000\)质数筛出来,然后用循环在 \(p\)\(b\) 之间寻找质数,找到后向上翻倍,方便下一次处理。

听起来比较简单,这边提醒几个小问题:

  1. 注意被我们扫描过的数我们直接认为是同一集合的元素,如果在扫描的时候发现这一组中有被扫描过的数那么这一次扫描的所有数都同一归到那个数的集合下面。

  2. 注意每一次扫描完后存不存在没有数的情况。

注意细节,代码会有相应解释。

代码

#include<bits/stdc++.h>
using namespace std;
int pri[100001];
int check[100001];
int main(){
    int a,b,p;
    cin>>a>>b>>p;
    pri[0]=1;
    pri[1]=1;//这两个注意特判
    for(int i=2;i<=100001;i++){//循环记得从 2 开始
        for(int j=i;j<=100001/i;j++){
            pri[i*j]=1;
        }
    }//筛素数
    int ans=0,sum=0;
    //ans为元素个数大于等于 2 的集合个数
    //sum为ans个集合中所有点的个数
    for(int i=p;i<=b;i++){//开始寻找
        if(pri[i]) continue;
        int t;
        if(a%i==0) t=a;
        else t=i*(a/i+1);//定义每一次扫描的端点
        int wyxak=0,tyqak=0;//这两个用来处理特殊情况
        //WYXkk AK IOI! Light_Tracing AK IOI!
        for(int j=t;j<=b;j+=i){//扫描此区间
            if(!check[j]){
                check[j]=1;
                wyxak=1;
                sum++;//找到后处理
            } 
            else tyqak=1;//没有数就将此判断变量改为 true
        }
        if(wyxak==1&&tyqak==0) ans++;//扫完若是此状况 ans 便可以加 1 了
    }
    cout<<ans+(b-a-sum+1);//b-a-sum+1 表示单个集合个数
    return 0;
}

具体就是这样,不懂还可以私信我。

管理员审核辛苦了!

posted @ 2020-03-06 22:45  Kriraya  阅读(107)  评论(0)    收藏  举报