P1621 集合

题目链接:https://www.luogu.com.cn/problem/P1621

思路

发现1e5/2+ 1e5/3 + 1e5/5+1e5/7+....的结果不到1e6,所以可以直接采用暴力,对于每个质因数P把在[L,R]区间的倍数join一下就行

代码

#include<bits/stdc++.h>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define debug  freopen("in.txt","r",stdin),freopen("out.txt","w",stdout);
#define fs first
#define sc second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 1e6+10;
using namespace std;

int L,R,p;
bool vis[maxn];
int P[maxn/10],tail;
int fa[maxn];
void initP(int N){
    for(int i = 2; i <=N; i++){
        if(!vis[i]) P[tail++] = i;
        for(int j = 0; P[j] <= N / i; j++){
            vis[P[j] * i] = true;
            if(i % P[j] == 0) break;
        }
    }
}
int find(int x){
    return fa[x] == x? x: fa[x] = find(fa[x]);
}
void join(int x,int y){
    fa[find(x)] = fa[find(y)];
}
int main(){
    // debug;
    ios;
    initP(100010);
    cin>>L>>R>>p;
    for(int i = L;i<=R;i++) fa[i] = i;
    for(int i = 0;i<tail;i++){
        if(P[i]<p) continue;
        for(int j = R/P[i]-1;j*P[i]>=L;j--){
            join(j*P[i],(j+1)*P[i]);
        }
    }
    int ans = 0;
    for(int i = L;i<=R;i++) ans += (find(i) == i);
    cout<<ans<<'\n';

    return 0;
}