[2020 CCPC 威海 L] Clock Master

https://codeforces.ml/gym/102798/problem/L
题意:
转换一下题意,就是问你现有\(b\)元,物品\(i(1 \leq i \leq 30000)\)拥有的权值和花费都是它对应的下标,问你怎么买使得你购买的物品的权值的\(LCM\)最大,输出\(ln(LCM)\)

思路:
用钱买东西,往背包去靠。我们想要让物品权值\(LCM\)最大,应该让所有物品的权值互质。然后我们再考虑一下,如果一个数字有多个质因数,那么它一下子会占多个坑,同时它本身的大小也比它质因数的和要大,很容易会让我们最终求出来的\(LCM\)变小。例如,我们取了\(6\),那么所有\(2\)的次方数和\(3\)的次方数都不能取了,但是我们只取\(2\)\(3\),只用花费\(5\)元就可以对LCM产生\(6\)个贡献。因此,我们考虑只取素数的次方数,并且每个素数的次方数中,我们只能取一个。这道题就变成了一道多组背包问题。同时注意到每次取的时候,物品都是不变的,而\(1 \leq T, b \leq 30000\),我们需要提前预处理出所有情况,最后\(O(1)\)查询就可以了,\(dp\)里直接传\(ln\)值的和。

训练的时候这道题心态都写崩了。不知道\(ln\)能直接求,先写了个二分求的,然后之后一直瞎构造,最后都没搞出来。对于用钱买东西还不够敏感,没有往背包上去想,太菜了QAQ

#include <bits/stdc++.h>

using namespace std;

const int N = 3e4;

int flag[N + 7], prime[N + 7], cnt;
double dp[N + 7], ln[N + 7];
vector<int> v[N];
int n;

void isprime() {
    for (int i = 2; i <= N; ++i) {
        if (!flag[i]) {
            prime[++cnt] = i;
        }
        for (int j = 1; j <= cnt; ++j) {
            if (1ll * i * prime[j] > N) break;
            flag[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}

void init() {
    isprime();
    for (int i = 1; i <= cnt; ++i) {
        int now = prime[i];
        v[i].push_back(now);
        while (1) {
            now *= prime[i];
            if (now > 30000) break;
            v[i].push_back(now);
        }
    }
    for (int i = 1; i <= 30000; ++i) {
        ln[i] = log(i);
    }
    
    memset(dp, 0xfe, sizeof(dp));
    dp[0] = 0;
    for (int i = 1; i <= cnt; ++i) {
        for (int w = 30000; w >= 1; --w) {
            for (int j = 0; j < v[i].size(); ++j) {
                int val = v[i][j];
                if (w < val) break;
                dp[w] = max(dp[w - val] + ln[val], dp[w]);
            }
        }
    }
    dp[1] = 0;
    double maxx = dp[1];
    for (int i = 2; i <= 30000; ++i) {
        dp[i] = max(dp[i], maxx);
        maxx = dp[i];
    }
}

void solve() {
    scanf("%d", &n);
    printf("%.9f\n", dp[n]);
}

int main() {
    init();
    int t = 1;
    scanf("%d", &t);
    while (t--) solve();
    return 0;
}
posted @ 2021-03-25 13:19  stff577  阅读(84)  评论(0)    收藏  举报