zoukankan      html  css  js  c++  java
  • hihocoder 1158 质数相关 dp

    描述

    两个数a和 b (a<b)被称为质数相关,是指a × p = b,这里p是一个质数。一个集合S被称为质数相关,是指S中存在两个质数相关的数,否则称S为质数无关。如{2, 8, 17}质数无关,但{2, 8, 16}, {3, 6}质数相关。现在给定一个集合S,问S的所有质数无关子集中,最大的子集的大小。

    输入

    第一行为一个数T,为数据组数。之后每组数据包含两行。

    第一行为N,为集合S的大小。第二行为N个整数,表示集合内的数。

    输出

    对于每组数据输出一行,形如"Case #X: Y"。X为数据编号,从1开始,Y为最大的子集的大小。

    数据范围

    1 ≤ T ≤ 20

    集合S内的数两两不同且范围在1到500000之间。

    小数据

    1 ≤ N ≤ 15

    大数据

    1 ≤ N ≤ 1000

    样例输入

    3
    5
    2 4 8 16 32
    5
    2 3 4 6 9
    3
    1 2 3
    

    样例输出

    Case #1: 3
    Case #2: 3
    Case #3: 2

    #include<string.h>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<malloc.h>
    #include<time.h>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<cstdlib>
    #include<set>
    #include<map>
    using namespace std;
    typedef  long long LL;
    #define kmax 500000
    LL prim[kmax+100],cnt,vit[kmax+100];
    LL p[1010],n;
    map<LL,LL>lk;
    vector<LL>ko[kmax+100];
    LL deep[1010],dp[1010];
    void getprim(){
        cnt=0;
        memset(vit,0,sizeof(vit));
        for(LL i=2;i<=kmax;i++){
            if(!vit[i]){
                prim[++cnt]=i;
            }
             for(LL j=1;j<=cnt&&prim[j]*i<=kmax;j++){
                  vit[prim[j]*i]=1;
                  if(i%prim[j]==0) break;
                }
        }
    }
    void bfs(LL pos){
        int sum=0;
        queue<LL>tmp;
        while(!tmp.empty()) tmp.pop();
        tmp.push(p[pos]);
        while(!tmp.empty()){
            LL to=tmp.front(),pe=deep[lk[to]];tmp.pop();vit[to]=0;
            for(LL i=0;i<ko[to].size();i++){
                LL num=ko[to][i];
                if(vit[num]) {
                    deep[lk[num]]=pe+1;
                    tmp.push(num);
                }
            }
            sum++;
        }
    }
    LL getans(LL pos){
        if(ko[p[pos]].size()==0) return 1; // 这个数可以与任何一个数同时存在
        LL mmax=1;
        memset(deep,0,sizeof(deep));
        memset(dp,0,sizeof(dp));
        deep[pos]=1;
        bfs(pos);   // 求与 p[pos] 这个数有边的数 deep 值
        for(LL i=0;i<n;i++) if(deep[i]) dp[deep[i]]++,mmax=max(mmax,deep[i]);// 舒适化dp
        for(LL i=2;i<=mmax;i++) dp[i]=max(dp[i]+dp[i-2],dp[i-1]);
        return dp[mmax];
    }
    int main(){
        getprim();
        LL t,cas=0;cin>>t;
        while(t--){
            cin>>n;
            memset(vit,0,sizeof(vit));
            for(LL i=0;i<n;i++) cin>>p[i],ko[p[i]].clear(),vit[p[i]]=1;lk.clear();
            sort(p,p+n);
            for(LL i=0;i<n;i++) lk[p[i] ]=i;
            /* 给质数相关的数建边*/
            for(LL j=0;j<n;j++){
                for(LL k=1;k<=cnt;k++){
                    if(1ll*p[j]*prim[k]>p[n-1]) break;
                    if(vit[p[j]*prim[k]]){
                        ko[p[j] ].push_back(p[j]*prim[k] );
                        ko[p[j]*prim[k]].push_back(p[j]);
                    }
                }
            }
            LL ans=0;
            for(LL i=0;i<n;i++)
            if(vit[p[i]]){
                ans+=getans(i);
            }
            printf("Case #%lld: %lld
    ",++cas,ans);
        }
    }
  • 相关阅读:
    数据安全:1.98亿购车者的购车记录公之于众
    【作者面对面问答】包邮送《Redis 5设计与源码分析》5本
    关于区块链学习资料
    《机器学习》周志华西瓜书学习笔记(九):聚类
    Bulletproof零知识证明
    数据接收合并
    数据接收合并
    数据接收合并
    数据接收合并
    Tomcat 8 Host-Manager配置访问的方法,全网唯一正确配置
  • 原文地址:https://www.cnblogs.com/ainixu1314/p/4464031.html
Copyright © 2011-2022 走看看