• 二分图 + 离散


    唐纳德是一个数学天才。有一天,他的数学老师决定为难一下他。他跟唐纳德说:「现在我们来玩一个游戏。这个游戏总共 n 轮,每一轮我都会给你一个数(第 i 轮给出的数是 ai)。你每次要回答一个数,是我给出的这个数的质因数,并且你说出的数不能重复。」

    因为数学老师是刻意为难,所以这个游戏很有可能不可能进行到最后。但是聪明的数学老师早就已经知道这个游戏最多能进行几轮了。现在他把问题抛给了你,想看看你知不知道。

    注意,1 不是质数。

    Input

    输入具有如下形式:

    na1 a2  an

    第一行一个整数 n (1n3 000)。

    第二行 n 个整数用空格隔开,a1,a2,,an (2ai106)。

    Output

    输出游戏最多能进行几轮。

    Examples

    Input
    3
    7 6 3
    
    Output
    3
    
    Input
    5
    2 2 2 2 2
    
    Output
    1

    思路 : 首先 要找出 每个数所有的不同质因数, 然后 我写了一个深搜 , 不出所料 , 超时了
        然后 细细想想,由于每个数只能对应一个数,因此可以用二分图匹配去搞,再由于质因数的范围比较大,因此可以离散,建边去匹配 , 但是 , 又超时了 !
        然后我就开始 怀疑二分匹配的复杂度是不是太高了,一顿百度,还没找到, 又想到了 是不是我找质因数的时候复杂度太高了,我优化了一下找质因数的方法,果然A了
        一个数的质因数只需要找到 根号 n ,因为不可能存在两个质因数大于 根号 n
    代码示例 :
    const int eps = 1e6+5;
    #define ll long long
    
    bool pt[1000];
    vector<int> pre[3005];
    int n;
    int xx[10000];
    bool ff[eps];
    int pp = 1;
    bool uu[10000];
    int oo[10000];
    
    bool find(int x){
        for(int i = 0; i < pre[x].size(); i++){
            int num = lower_bound(xx+1, xx+pp, pre[x][i]) - xx;
            if (!uu[num]){
                uu[num] = true;
                if (oo[num] == 0 || find(oo[num])){
                    oo[num] = x;
                    return true;
                }           
            }
        }
        return false;
    }
    
    void fun(int k, int x){
        int uu = x;
        for(int i = 2; i <= sqrt(uu)+1; i++){
            if (pt[i]){
                int f = i;
                if (x % f == 0){
                    pre[k].push_back(f);
                    if (!ff[f]) {
                        xx[pp++] = f; 
                        ff[f] = true;
                    }
                }
                while(x % f == 0) x /= f;
            }
            if (x == 1) break;
        }
        if (x != 1){
            pre[k].push_back(x);
            if (!ff[x]){
                xx[pp++] = x;
                ff[x] = true;
            }
        }
    }
    
    int main() {
        cin >> n;
        int cn;
        
        memset(pt, true, sizeof(pt));
        for(int i = 2; i <= 1000; i++){
            if (pt[i]) {
                for(int j = i + i; j <= 1000; j += i){
                    pt[j] = false;
                }
            }
        }
        memset(ff, false, sizeof(ff)); 
        for(int i = 1; i <= n; i++){
            scanf("%d", &cn);
            fun(i, cn);
            //pre[i].erase(unique(pre[i].begin(), pre[i].end()), pre[i].end());
        }
        sort(xx+1, xx+pp); 
        memset(oo, 0, sizeof(oo));
        //for(int i = 1; i <= n; i++){
            //for(int j = 1; j < pp; j++){
                //if (edge[i][j]) printf("%d ", 1);
                //else printf("0 ");
            //}
            //printf("
    ");
        //}
        int ans = 0;
        for(int i = 1; i <= n; i++){
            memset(uu, false, sizeof(uu));
            if (find(i)) {
                ans++;
            }
            else break;
        }
        printf("%d
    ", ans);
    
        return 0;
    }
    

    东北日出西边雨 道是无情却有情
  • 相关阅读:
    跳跃表原理
    ThreadLocal
    Innodb中的事务隔离级别和锁的关系
    线程池拒绝策略
    vue 的 nextTick 原理
    Git 的基本操作
    JavaScript 的运行机制
    实现一个react系列三:生命周期
    实现一个react系列二:渲染组件
    实现一个react系列一:JSX和虚拟DOM
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8021602.html
Copyright © 2020-2023  润新知