CCPC2021河北省赛 K.Kate and Company Management(dp、质因数分解)

  • 题意:给出n个人的能力值ai,需将其从大到小进行排序若挑选出来的两人gcd(ai, aj) != 1, 则该两人可以组合在一个队伍中(并且相邻),一个队伍中不相邻的两人可以不用满足gcd != 1的条件,这n个人能组合在一个队伍里最多能有几个人,若人数小于3输出-1,否则输出队伍最多的人数.
  • 思路:Dp + 质因数分解
  • 解析:若gcd(ai, aj) != 1说明ai与aj必然有相同的质因数;
    1. dp[i]表示到第i个人为止,该队伍最多能有的人数
    2. m[x]表示质因数x在1-(i-1)的能力值序列中,一些子序列并且这些子序列结尾的能力值质因数包含x的最长子序列长度 例如:20(2, 2, 5) 、18(2, 3, 3)、 9(3, 3)
      那么从i = 1开始, m[2] = 1, m[5] = 1;
      i = 2,m[2] = 2, m[3] = 2;
      i = 3, m[3] = 2 + 1 = 3.
      其实这里有一个很巧妙的关系,20与18的相同质因数是2,而18与9的相同质因数是3,而gcd(20, 9) = 1,所以他们两个不能直接相连,但是可以通过18将其二者相连接,所m[x]代表的是1 - (i-1)个数挑选出满足条件的子序列并且子序列结尾的值的质因素包含x的最大长度(语文功底太差了,写的好费劲~~~)
    3. dp[i] = max(dp[i], m[x] + 1);
    4. 最后需要将m[x]更新,m[x] = dp[i];
  • ps:这题的dp听大佬讲后都挺难理解的,就大概写了一下题解,搜了一下网上也没见有题解(真不懂怎么写~~)
  • 代码:
#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
const int N = 3e5 + 5;
const int M = 1e5 + 5;
int prime[M], vis[M];
map<int, int> m;
vector<int> fac[N];
int dp[N], a[N];
int n, cnt = 0;
bool cmp(int a, int b)
{
    return a > b;
}
void init() //素数打表
{
    vis[0] = vis[1] = 1;
    for(int i = 2; i <= 1e5; i++)
    {
        if(!vis[i]) prime[++cnt] = i;
        for(int j = 1; j <= cnt && i * prime[j] <= 1e5; j++)
        {
            vis[i * prime[j]] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}
void getfac() //质因数分解
{
    for(int i = 1; i <= n; i++)
    {
        int val = a[i];
        int num = 1;
        while(val > 1)
        {
            if(!vis[val]) //val为素数
            {
                fac[i].push_back(val);
                val = 1;
                break;
            }
            while(val % prime[num] == 0)
            {
                fac[i].push_back(prime[num]);
                val /= prime[num];
            }
            num ++;
        }
    }
}
int main()
{
    init();
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    sort(a + 1, a + 1 + n, cmp);
    getfac();
    for(int i = 1; i <= n; i++)
    {
        for(int j = 0; j < fac[i].size(); j++)
        {
            int x = fac[i][j];
            dp[i] = max(dp[i], m[x] + 1);
        }
        for(int j = 0; j < fac[i].size(); j++)
        {
            int x = fac[i][j];
            m[x] = dp[i];
        }
    }
    int res = -1;
    for(int i = 1; i <= n; i++)
        res = max(res, dp[i]);
    if(res > 3) cout << res << endl;
    else cout << "-1" << endl;
    return 0;
}

上一篇:基于SSM框架的手机商城设计与实现毕业论文+任务书+项目源码及数据库


下一篇:ssh mysql jsp码头船只出行及配套货柜码放管理系统的设计与实现