卧薪尝胆,厚积薄发。
Bookshelves
Date: Thu Sep 20 21:11:34 CST 2018
In Category:
NoCategory
Description:
把一个长为
$n$
的序列划分成
$k$
段,最大化每段和的
$\text{and}$
和。
$1\le n,k \le 50$
Solution:
按位贪心
$DP$
验证的套路,从高到低枚举每一位,这一位可以为一当且仅当所有区间和这一位都为一,且所有区间和的更高位都满足之前的限制,
$n$
和
$k$
都很小
$DP$
就行了。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,k;
#define MAXN 60
typedef long long ll;
ll a[MAXN];
bool f[MAXN][MAXN];
ll sum[MAXN];
int main()
{
scanf("%d%d",&n,&k);
for(int i = 1;i <= n;++i)
{
scanf("%lld",&a[i]);
sum[i] = sum[i - 1] + a[i];
}
ll val = 0;
for(ll b = 62;b >= 0;--b)
{//cout << b << " : " << endl;
memset(f,false,sizeof(f));
f[0][0] = true;
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= k;++j)
{
for(int l = 0;l < i;++l)
{
if((((sum[i] - sum[l]) & (1ll << b))) != 0 && (((sum[i] - sum[l]) & val) == val))
{
f[i][j] |= f[l][j - 1];
}
}
}
}
if(f[n][k])val |= (1ll << b);
}
cout << val << endl;
return 0;
}
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡