Prime Independence LightOJ - 1356 (Prime Factorization + Maximum Point Independence Set)

Prime Independence

LightOJ - 1356

A set of integers is called prime independent if none of its member is a prime multiple of another member. An integer a is said to be a prime multiple of b if,

a = b x k (where k is a prime [1])

So, 6 is a prime multiple of 2, but 8 is not. And for example, {2, 8, 17} is prime independent but {2, 8, 16} or {3, 6} are not.

Now, given a set of distinct positive integers, calculate the largest prime independent subset.


Input

Input starts with an integer T (≤ 20), denoting the number of test cases.

Each case starts with an integer N (1 ≤ N ≤ 40000) denoting the size of the set. Next line contains N integers separated by a single space. Each of these N integers are distinct and between 1 and 500000 inclusive.

Output

For each case, print the case number and the size of the largest prime independent subset.

Sample Input

3

5

2 4 8 16 32

5

2 3 4 6 9

3

1 2 3

Sample Output

Case 1: 3

Case 2: 3

Case 3: 2

Note

1.      An integer is said to be a prime if it's divisible by exactly two distinct integers. First few prime numbers are 2, 3, 5, 7, 11, 13, ...

2.      Dataset is huge, use faster I/O methods.

Original blog addressClick to open the link

Restriction: If a % b == 0 && a / b = k where k is a prime number, then a and b cannot exist in a set at the same time.

The meaning of the question: give you n numbers, let you find the largest set that satisfies the above constraints, and output the number of elements.



Idea: Build a bipartite graph according to the parity of the number of prime factors of each number, and construct a good graph. Let's run HK, Hungary didn't dare to write, and even my HK didn't dare to use vector.


Mapping: It is not possible to traverse the mapping with a two-layer for loop, and the O(n*n) mapping complexity cannot be afforded. You can find all prime factors p[] of each number a[i], judge whether a[i] / p[] exists, and then build a map according to the parity. In this way, the worst time complexity of mapping is O(n*10), and then adding HK, the total time complexity

O(sqrt(n) * m + n * 10)。

code:

    #include <cstdio>  
    #include <cstring>  
    #include <algorithm>  
    #include <vector>  
    #include <queue>  
    #define MAXN 40000+10  
    #define MAXM 1000000+10  
    #define INF 0x3f3f3f3f  
    #define debug printf("1\n");  
    using namespace std;  
    struct Edge{  
        int to, next;  
    };  
    Edge edge[MAXM];  
    int head[MAXN], edgenum;  
    int P[500010], num[500010];//Record whether each number is a prime number record the number of prime factors in each number  
    int a[MAXN];  
    int id[MAXN];  
    int oddnum, evennum;  
    void getP()  
    {  
        memset(P, 0, sizeof(P));  
        for(int i = 2; i <= 500000; i++)  
        {  
            if(P[i]) continue;  
            for(int j = 2*i; j <= 500000; j+=i)  
                P[j] = 1;  
        }  
        P[1] = 1;  
    }  
    //vector<int> p[500000+10];  
    void getPsum()  
    {  
        for(int j = 1; j <= 500000; j++)  
        {  
            int cnt = 0;  
            int n = j;  
            for(int i = 2; i * i <= n; i++)  
            {  
                if(n % i == 0)  
                {  
                    while(n % i == 0)  
                    {  
                        cnt++;  
                        n /= i;  
                    }  
                }  
            }  
            if(n > 1)  
                cnt++;  
            num[j] = cnt;  
        }  
    }  
    void init(){  
        edge = 0;  
        memset(head, -1, sizeof(head));  
    }  
    void addEdge(int u, int v)  
    {  
        Edge E1 = {v, head[u]};  
        edge[edgenum] = E1;  
        head[u] = edgenum++;  
    }  
    int n;  
    int force[500010];  
    int p[30], top;  
    void getprime(int n)  
    {  
        top = 0;  
        for(int i = 2; i * i <= n; i++)  
        {  
            if(n % i == 0)  
            {  
                p[top++] = i;  
                while(n % i == 0)  
                    n /= i;  
            }  
        }  
        if(n > 1)  
            p[top++] = n;  
    }  
    void getMap()  
    {  
        scanf("%d", &n);  
        oddnum = evennum = 0;  
        memset(vis, 0, sizeof(vis));  
        for(int i = 1; i <= n; i++)  
        {  
            scanf("%d", &a[i]);  
            vis[a[i]] = i;//Mark the element has appeared  
            if(num[a[i]] & 1)  
                id[i] = ++oddnum;  
            else  
                id[i] = ++evennum;  
        }  
        init();  
        for(int i = 1; i <= n; i++)  
        {  
            getprime(a[i]);//Process prime factor  
            for(int j = 0; j < top; j++)  
            {  
                int goal = a[i] / p[j];  
                int index = vis[goal];  
                if(index)//exist  
                {  
                    if(num[a[i]] & 1 && num[a[index]] % 2 == 0)  
                        addEdge(id[i], id[index]);  
                    else if(num[a[i]] % 2 == 0 && num[a[index]] & 1)  
                        addEdge(id[index], id[i]);  
                }  
            }  
        }  
    }  
    bool used[MAXN];  
    int dx[MAXN], dy[MAXN];  
    int mx[MAXN], my[MAXN];  
    you are DFS (you are)  
    {  
        for(int i = head[u]; i != -1; i = edge[i].next)  
        {  
            int v = edge[i].to;  
            if(!used[v] && dy[v] == dx[u] + 1)  
            {  
                used[v] = true;  
                if(my[v] == -1 || DFS(my[v]))  
                {  
                    my[v] = u; mx[u] = v;  
                    return 1;  
                }  
            }  
        }  
        return 0;  
    }  
    int kcase = 1;  
    void HK()  
    {  
        memset(mx, -1, sizeof(mx));  
        memset(my, -1, sizeof(my));  
        int years = 0;  
        while(1)  
        {  
            bool flag = false;  
            memset(dx, 0, sizeof(dx));  
            memset(dy, 0, sizeof(dy));  
            queue<int> Q;  
            for(int i = 1; i <= oddnum; i++)  
                if(mx[i] == -1)  
                    Q.push(i);  
            while(!Q.empty())  
            {  
                int u = Q.front();  
                Q.pop();  
                for(int i = head[u]; i != -1; i = edge[i].next)  
                {  
                    int v = edge[i].to;  
                    if(!dy[v])  
                    {  
                        dy[v] = dx[u] + 1;  
                        if(my[v] == -1)  
                            flag = true;  
                        else  
                        {  
                            dx[my[v]] = dx[u] + 1;  
                            Q.push(my[v]);  
                        }  
                    }  
                }  
            }  
            if(!flag) break;  
            memset(used, false, sizeof(used));  
            for(int i = 1; i <= oddnum; i++)  
                if(mx[i] == -1)  
                    ans += DFS(i);  
        }  
        printf("Case %d: %d\n", kcase++, n - ans);  
    }  
    intmain()  
    {  
        getP();  
        getPsum ();  
        int t;  
        scanf("%d", &t);  
        while(t--)  
        {  
            getMap();  
            HK ();  
        }  
        return 0;  
    }  


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324518926&siteId=291194637