CF981D 书架

1 CF981D 书架

2 题目描述

时间限制 \(1s\) | 空间限制 \(256M\)

\(Keks\) 先生是 \(Byteland\) 的典型白领。他在办公室有一个书架,上面放着一些书,每本书的价格都是正整数。\(Keks\) 先生把书架的价值定义为书架上的书的价格之和。\(Keks\) 先生获得了晋升,现在他正要搬到新办公室。他了解到在新办公室里,他会有 \(k\) 个书架。他认为 \(𝑘\) 个书架的美丽值是所有书架的价值按位与的结果。他决定不花时间重新排列所有的书籍,所以第一个书架上会摆上很多本第一批书,下一批次书摆在下一个书架上,以此类推。每个书架上最少有一本书。通过这种方式他把所有的书都放在 \(k\) 个书架上并且书架的美丽值尽可能大。请计算可能的最大美丽值。

3 题解

这道题中,我们考虑从高位到低位满足:高位答案为 \(1\) 比低位答案为 \(1\) 明显更优。对于当前位,我们可以设计 \(dp_{i, j}\) 表示前 \(i\) 本书放到前 \(j\) 个书架中能否满足当前答案(注意一定包括之前求出来的数,否则如果只看能否满足当前位 \(p\),可能导致无法满足之前的答案)。我们发现:如果只循环 \(i, j\) 两维貌似无法转移,因为我们不知道上一个书架结束的位置在哪里。因此,我们再枚举一维 \(l\),表示第 \(i\) 本书所位于的书架从第 \(l\) 本书开始。这样,我们只需要查看:\(ans \space \& \space \sum_{k = l}^{i}\limits a_i\) 是否等于 \(ans\),同时 \(dp_{l-1, j-1}\) 是否等于 \(1\)。如果这两个条件都满足,那么当前位就可以满足答案,\(dp_{i, j} = 1\)

最后,我们的答案 \(ans\) 加上 \(dp_{n, k} * 2^p\) 即可。注意对于每一位要先把 \(dp\) 值清 \(0\)

4 代码(空格警告):

#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 60;
#define int long long
int n, k, cnt, ans;
int a[N], sum[N], dp[N][N];
signed main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; i++) cin >> a[i], sum[i] = sum[i-1] + a[i];
    for (int p = N; p >= 0; p--)
    {
        memset(dp, 0, sizeof(dp));
        dp[0][0] = 1;
        cnt = ans + (1ll << p);
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= k; j++)
            {
                for (int l = 1; l <= i; l++)
                {
                    if ((cnt & (sum[i] - sum[l-1])) == cnt && dp[l-1][j-1]) dp[i][j] = 1;
                }
            }
        }
        ans += dp[n][k] * (1ll << p);
    }
    cout << ans;
    return 0;
}

欢迎关注我的公众号:智子笔记

posted @ 2021-02-14 10:43  David24  阅读(124)  评论(0编辑  收藏  举报