CJOJ 1504 整数合并

来源:互联网 发布:format java 编辑:程序博客网 时间:2024/06/07 18:48

整数合并

Description

现在给你一些连续的整数,它们是从 A 到 B 的整数。一开始每个整数都属于各自的集合,然后你需要进行如下操作:
每次选择两个属于不同集合的整数,如果这两个整数拥有大于等于 P 的公共质因子,那么把他们所在的集合合并。
反复上述操作,直到没有可以合并的集合为止。
现在,小 X 想知道,最后有多少个集合。

Input

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

Output

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

Sample Input

10 20 3

Sample Output

7

Hint

样例解释:
解释: {10 , 20 , 12 , 15 , 18} , {11},{13} , {14} , {16} , {17} , {19}
【数据规模】
B<=1000. 80%数据
A<=B<=100000; 2<=P<=B

Source

并查集 ,数学 ,数论

Solution

对于有相同质因数的数字加入一个集合,最后统计集合的个数即可(爸爸是自己的点的个数)

Code

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <stack>#include <map>#include <vector>#include <queue>#define L 100010#define LL long longusing namespace std;int a, b, p, prim[L], cnt, f[L], ans;bool check[L];inline int find(int x) { return (f[x] == x) ? x : f[x] = find(f[x]);}inline void makeset(int x, int fa) {f[find(x)] = f[find(fa)];}int main() {  freopen("CJOJ1504.in", "r", stdin);  freopen("CJOJ1504.out", "w", stdout);  scanf("%d %d %d", &a, &b, &p);  for (int i = a; i <= b; ++i) f[i] = i;  for (int i = 2; i <= b; ++i) {    if (!check[i]) prim[++cnt] = i;    for (int j = 1; j <= cnt && i * prim[j] <= b; ++j) {      check[prim[j] * i] = 1;      if (i % prim[j] == 0) break;    }  }  for (int i = 1; i <= cnt; ++i)    if (prim[i] >= p) {      int c = a / prim[i] * prim[i];      if (c != a) c += prim[i];      for (int j = c + prim[i]; j <= b; j += prim[i]) makeset(j, c);    }  for (int i = a; i <= b; ++i) if (f[i] == i) ans++;  printf("%d\n", ans);  return 0;}

Summary

注意合并集合的时候试讲他们的父亲放在一起,以及初始化的时候初始自己的父亲是自己

0 0