1. 程式人生 > >CF-Avito Code Challenge 2018-D-Bookshelves

CF-Avito Code Challenge 2018-D-Bookshelves

ACM模版

描述

這裡寫圖片描述

題解

按位貪心,dpcheck

稍微詳細點說,那就是按照二進位制位從高位開始往低位貪心,貪心第 bit 位時,檢查是否可以達成分為 k 堆,每堆和的第 bit 位為 1,如果可以則累計。檢查的時候用 dp 進行檢查,檢查的複雜度是 O(n3),加上貪心的複雜度,一共是 O(an3)a 的大小和 n 差不多,所以總得複雜度約莫是 O(n4),這裡需要注意一下,最高位不能從 50 開始,51 也不行,會被 hack(血淋淋的教訓),最好大於 55,因為最糟糕的情況時,給定

50 個數,分為一堆,每個數都是 2501,那麼和就是 2505050>25025,……,所以最好開大一些保險。

程式碼

#include <iostream>
#include <cstring>

using namespace std;

typedef long long ll;

const int MAXN = 70;

int n, k;
ll a[MAXN];
ll s[MAXN];
ll dp[MAXN][MAXN];

int main(int argc, const char * argv[])
{
    cin
>> n >> k; for (int i = 1; i <= n; i++) { cin >> a[i]; s[i] = s[i - 1] + a[i]; } ll base_ = 0; for (int bit = 60; bit >= 0; bit--) { ll cnt = 1ll << bit; memset(dp, 0, sizeof(dp)); dp[0][0] = 1; for (int
i = 1; i <= k; i++) // i 堆 { for (int j = 1; j <= n; j++) // 前 j 個數 { for (int k = 0; k < j; k++) // 前 k < j 個數 { if (dp[i - 1][k] && ((s[j] - s[k]) & cnt) && (((s[j] - s[k]) & base_) == base_)) { dp[i][j] = 1; } } } } if (dp[k][n]) { base_ += cnt; } } cout << base_ << '\n'; return 0; }