2020ICPC·小米 网络选拔赛第一场 A Intelligent Warehouse(dp)

链接:https://ac.nowcoder.com/acm/contest/7501/A
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

In MI Intelligent Warehouse, there are nn_{}n​ products, where the ii_{}i​-th product is of size aia_iai​. We always need to box producsts into all kinds of containers, and it will be safer and more cost efficient if for any two sizes of products, one is the other's multiple, since there won't be any residual room in one container. So for each boxing we need to choose some products that for any two chosen products, either aia_iai​ is multiple of aja_jaj​ or aja_jaj​ is multiple of aia_iai​. Print the maximum number of products that can be chosen in one boxing.

输入描述:

 

The first line contains one integer n (1≤n≤2×105)

The second line contains n integers a1,a2,⋯ ,an (1≤ai≤107)

输出描述:

Only one line containing one integer, denoting the maximum number of products we can choose in one boxing.

示例1

输入

6
1 4 2 8 5 7

输出

4

说明

One possible choice is {1, 4, 2, 8}.

题意:给一个数列,问最多可以选择多少个数,其中任意两数之间都有倍数关系

思路:每个数是由它的因子转移过来的,一种方法是用每个数更新它的倍数,复杂度是O(nlogn),可能会TLE;实际上只需要枚举 i 的素数倍就可以了,因为合数都可以被若干素数的乘积表示出来,复杂度O(nloglogn)

(正解是第二种方法,不过第一种也能卡过)

比较一下:

正解:

暴力枚举倍数:

今日flag:从今后手写max、再也不用快写

------------------------------------------------------------------------------------------------------------------

正解:

#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 1e7 + 7;
int pri[N], tot;
bool vis[N];

inline int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while(!isdigit(ch)) {
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(isdigit(ch)) {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}

void init() {
    for(int i = 0; i < N; ++i) vis[i] = 0;
    vis[0] = vis[1] = 1;
    tot = 0;
    for(int i = 2; i < N; ++i) {
        if(!vis[i]) {
            pri[++tot] = i;
            for(int j = i + i; j < N; j += i)
                vis[j] = 1;
        }
    }
}

int dp[N], a, n, cnt[N];

int main() {
    init();
    n = read();
    int maxx = 0;
    for(int i = 1; i <= n; ++i) {
        a = read();
        if(maxx < a) maxx = a;
        cnt[a]++;
    }
    int ans = 0;
    for(int i = 1; i <= maxx; ++i) {
        dp[i] += cnt[i];
        for(int j = 1; j <= tot && pri[j] * i <= maxx; ++j)
            if(dp[pri[j] * i] < dp[i]) dp[pri[j] * i] = dp[i];
        if(ans < dp[i]) ans = dp[i];
    }
    printf("%d\n", ans);
    return 0;
}

第一种:(暴力

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 1e7 + 10;

inline int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while(!isdigit(ch)) {
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(isdigit(ch)) {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}

int a[N], st[N], dp[N];
int cnt[N];

int main() {
    int n, a, tot = 0, maxx = 0;
    n = read();
    for(int i = 1; i <= n; ++i) {
        a = read();
        if(maxx < a) maxx = a;
        if(!cnt[a]) st[++tot] = a;
        cnt[a]++;
    }
    sort(st + 1, st + tot + 1);
    int ans = 0;
    for(int i = 1; i <= tot; ++i) {
        dp[st[i]] += cnt[st[i]];
        for(int j = st[i] + st[i]; j <= maxx; j += st[i]) {    ///这样写比j = 2; st[i] * j <= maxx快,because少算了好多乘法
            if(!cnt[j]) continue;
            if(dp[j] < dp[st[i]]) dp[j] = dp[st[i]];
        }
        if(ans < dp[st[i]]) ans = dp[st[i]];
    }
    printf("%d\n", ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43871207/article/details/109289292