传送门:P1621 集合 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
首先咱得清楚一个自L—R的区间内,有(R-L+1)个集合。
集合的判断与链接势必要用到并查集。
因子的判断可以与埃筛联系起来。(欧拉筛不适合因为它的提前退出)
题目对于因子的要求是大于等于题目给出的因子。所以我们在埃筛的时候因子如果不满足>=P就全都筛掉(过滤因子)。
#include<math.h>
#include<algorithm>
#include<time.h>
#include<stdlib.h>
#include<iostream>
#include<string.h>
#include<sstream>
#include<map>
#include<list>
#include<string>
#include<queue>
#include<set>
#include<vector>
#include<stack>
#include<limits>
#define re register
#define iosgo() std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define run(i,n) for (int i = 1; i <= n; i++)
#define cin std::cin
#define cout std::cout
#define ll long long
#define endl "\n"
using namespace std;
typedef pair<int, int>pll;
const int N = 2e6 + 10;
pll c[N];
int x[N], y[N], dp[N], ss[N], a[N], b[N];
bool flag[N];
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
int find(int v)
{
if (x[v] == v)return v;
else return x[v] = find(x[v]);
}
void merge(int u, int v)
{
int a = find(u);
int b = find(v);
if (a != b)
{
x[a] = b;
}
}
signed main()
{
iosgo();
int l, r, q;
cin >> l >> r >> q;
int ans = r - l + 1;
run(i, r)x[i] = i;
run(i, r)flag[i] = false;
for ( int i = 2; i <= r; i++)
{
if ( !flag[i] )
{
if (i >= q)//满足因子开始找
{
for ( int j = i; j <= r; j += i)//<=r设定了右边界
{
flag[j] = true;
if (j - i >= l)//>=l设定了左边界
{
if (find(j - i) != find(j))
{
merge(j, j-i);//只要有新的链接,那么集合-1.
ans--;
}
}
}
}
else//筛筛筛
{
for (int j = i * i; j <= r; j += i)
{
flag[j] = true;
}
}
}
}
cout << ans <<endl;
}