zoukankan      html  css  js  c++  java
  • 洛谷P1621-集合

    Problem 洛谷P1621-集合

    Accept:496  Submit: 1.4k

    Time Limit: 1000 mSec    Memory Limit : 128MB

    Problem Description

    现在给你一些连续的整数,它们是从A到B的整数。一开始每个整数都属于各自的集合,然后你需要进行一下的操作:

    每次选择两个属于不同集合的整数,如果这两个整数拥有大于等于P的公共质因数,那么把它们所在的集合合并。

    反复如上操作,直到没有可以合并的集合为止。

    现在Caima想知道,最后有多少个集合。

     Input

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

    【数据规模】

    A≤B≤100000;

    2≤P≤B。

     Output

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

     Sample Input

    10 20 3

    Sample output

    7

    题目链接:https://www.luogu.org/problemnew/show/P1621

    题解:水题,之所以记录一下是因为感觉自己在做这道题的时候才感觉真的弄明白了欧拉筛的证明,以前会证明,但是感觉是只是机械化的证明,没有自己的理解。

    我认为证明中最精华的一句话是,在i%prime[j] == 0,之前,prime[j]均为i*prime[j]的最小素因子,这个结论很显然,但是起到了决定性作用......

    筛完素数就是简单的并查集。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 const int maxn = 100000+10;
     9 bool is_prime[maxn];
    10 int tot,prime[maxn];
    11 int pre[maxn];
    12 int a,b,p;
    13 
    14 void get_Prime(){
    15     memset(is_prime,true,sizeof(is_prime));
    16     is_prime[0] = is_prime[1] = false;
    17     tot = 0;
    18     for(int i = 2;i < maxn-1;i++){
    19         if(is_prime[i]) prime[tot++] = i;
    20         for(int j = 0;j<tot && prime[j]<=maxn/i;j++){
    21             is_prime[i*prime[j]] = false;
    22             if(i%prime[j] == 0) break;
    23         }
    24     }
    25 }
    26 
    27 int findn(int x){
    28     return x == pre[x] ? x : pre[x] = findn(pre[x]);
    29 }
    30 
    31 void merge_node(int x,int y){
    32     int fx = findn(x),fy = findn(y);
    33     if(fx != fy){
    34         pre[fx] = fy;
    35     }
    36 }
    37 
    38 int main()
    39 {
    40     //freopen("input.txt","r",stdin);
    41     get_Prime();
    42     scanf("%d%d%d",&a,&b,&p);
    43     for(int i = a;i <= b;i++){
    44         pre[i] = i;
    45     }
    46     int pos = lower_bound(prime,prime+tot,p)-prime;
    47     for(int i = pos;prime[i] <= b;i++){
    48         for(int j = 2;j*prime[i] <= b;j++){
    49             if((j-1)*prime[i] < a) continue;
    50             merge_node((j-1)*prime[i],j*prime[i]);
    51         }
    52     }
    53     int cnt = 0;
    54     for(int i = a;i <= b;i++){
    55         if(pre[i] == i) cnt++;
    56     }
    57     printf("%d
    ",cnt);
    58     return 0;
    59 }
  • 相关阅读:
    python 中文文档地址总结
    清除celery 任务队列
    celery work logging 问题
    mysql 数据库 存储数据类型
    python 补0的方法
    lunix 命令积累
    python3 import Crypto 失败的解决办法 (AES对称加密使用 模块)
    从excel 获取内容 模块:xlrd
    api h5 sdk 接入的说明
    Excel 打开两个单独的页面
  • 原文地址:https://www.cnblogs.com/npugen/p/9498921.html
Copyright © 2011-2022 走看看