zoukankan      html  css  js  c++  java
  • P1621 集合

     欧拉筛先把质数整出来,现在需要一个执行将任意具有不小于p的公共质因子的整数合并.

    我并没有看到什么求公共质因子的算法,而且就算有也只能想到O(N2)的合并方法.

    根据欧拉筛的启示,有如下方法:

      对于查找到的每一个质数pi>=p,合并pi,2pi,3pi...(直到即将越界).

    之后统计集合个数即得答案.

    这样操作之后可以使得任意以pi为公共质因子的整数处在同一个集合,现在只需要考虑另外一种情况,(假设各个pi形成的集合仍是相互独立的)即pi,pj两集合(设为A,B)是否合并.

    当遍历合并pi的倍数时,可以肯定,如果pi*pj没有越界,此时A,B将合并,否则一定不会合并.pi*pj不越界是A,B集合合并的充分必要条件.

      首先,遍历pi的倍数kp时,当k<pj,kp一定不会与pj有公因数.当k=pj,kp与pj一定有且仅有公因数pj.

    所以这个情况已经被包含在一般处理中了.

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    bool isPrime[100010];
    int a, b, p, fa[100010], ans;
    vector<int> s;
    
    int get(int x) {
        if (fa[x] == x) return x;
        return fa[x] = get(fa[x]);
    }
    void merge(int x, int y) { fa[get(x)] = fa[get(y)]; }
    void init(int n) {
        for (int i = 1; i <= b; i++) fa[i] = i;
        fill(isPrime, isPrime + 100010, 1);
        isPrime[1] = isPrime[0] = 0;
    
        for (int i = 2; i <= n; i++) {
            if (isPrime[i]) s.push_back(i);
            for (int j = 0; j < s.size() && i * s[j] <= n; j++) {
                isPrime[i * s[j]] = 0;
                if (i % s[j] == 0) break;
            }
        }
    }
    
    int main() {
        scanf("%d%d%d", &a, &b, &p);
        init(b);
    
        for (auto it = s.begin(); it != s.end(); it++) {
            if (*it < p) continue;
            for (int i = 2; i * (*it) <= b; i++) merge(*it, i * (*it));
        }
    
        // 统计答案
        bool used[100010] = {0};
        for(int i = a; i <= b; i++) used[get(i)] = true;
        for(int i = a; i <= b; i++) if(used[i]) ans++;
        printf("%d
    ", ans);
    
        return 0;
    }
    P1621
  • 相关阅读:
    CLR via C# 3rd Edition下载
    SQL中的CASE WHEN语句
    为何要写注释?
    插件购票的公平性分析
    数据查询
    国产操作系统的市场运作策略
    0/0=2?
    为什么0.1无法被二进制小数精确表示?
    .net 可能要遭到取缔
    思考问题要先注意主体
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14371789.html
Copyright © 2011-2022 走看看