#include <iostream>
#include <unordered_map>
#include <cmath>
#include <vector>
int64_t MIN_VAL = -9223372036854775807;
int64_t MAX_VAL = 9223372036854775807;
using namespace std;
std::vector<int64_t> sums;
std::vector<int64_t> lookup (200*200*60, MIN_VAL);
std::vector<int64_t> lookup2 (200*200*5000, MIN_VAL);
int64_t dp(vector<int64_t> const& pops, int start, int end, int64_t max_numb){
if(__builtin_popcountll(max_numb) == 1 && lookup[start* 200 * 60 + end * 60 + log2(max_numb)] != MIN_VAL){
return lookup[start* 200 * 60 + end * 60 + log2(max_numb)];
}
if(max_numb < 5000 && lookup2[start* 200 * 5000 + end * 5000 + max_numb] != MIN_VAL){
return lookup2[start* 200 * 5000 + end * 5000 + max_numb];
}
if(end == start){
return 0;
}
if(end - start > max_numb){
return MIN_VAL;
}
if(end - start == max_numb){
int64_t ret = 0;
int64_t counter = 0;
for(int64_t i = start; i < end; i ++){
ret += __builtin_popcountll(counter) * pops[i];
counter ++;
}
return ret;
}
int64_t maxpow = 1;
while(maxpow * 2 < max_numb){
maxpow *= 2;
}
int64_t ret = MIN_VAL;
for(int i = start; i <= end; i ++){
int64_t sum = sums[i] - sums[end];
int64_t left = dp(pops, start, i, maxpow);
int64_t right = dp(pops, i, end, max_numb - maxpow);
if(left != MIN_VAL && right != MIN_VAL){
ret = max(ret, sum + left + right);
}
}
if(__builtin_popcountll(max_numb) == 1){
lookup[start* 200 * 60 + end * 60 + log2(max_numb)] = ret;
}
if(max_numb < 5000){
lookup2[start* 200 * 5000 + end * 5000 + max_numb] = ret;
}
return ret;
}
int main(){
int64_t n;
int64_t m;
cin >> n;
cin >> m;
vector<int64_t> pops;
pops.reserve(n);
int64_t sum = 0;
sums.push_back(0);
for(int i = 0; i < n; i++){
int64_t tmp;
cin >> tmp;
sum += tmp;
sums.push_back(sum);
pops.push_back(tmp);
}
for(auto & cur: sums){
cur = sum - cur;
}
m++;
cout << dp(pops, 0, pops.size(), m) << endl;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | #include <iostream> #include <unordered_map> #include <cmath> #include <vector> int64_t MIN_VAL = -9223372036854775807; int64_t MAX_VAL = 9223372036854775807; using namespace std; std::vector<int64_t> sums; std::vector<int64_t> lookup (200*200*60, MIN_VAL); std::vector<int64_t> lookup2 (200*200*5000, MIN_VAL); int64_t dp(vector<int64_t> const& pops, int start, int end, int64_t max_numb){ if(__builtin_popcountll(max_numb) == 1 && lookup[start* 200 * 60 + end * 60 + log2(max_numb)] != MIN_VAL){ return lookup[start* 200 * 60 + end * 60 + log2(max_numb)]; } if(max_numb < 5000 && lookup2[start* 200 * 5000 + end * 5000 + max_numb] != MIN_VAL){ return lookup2[start* 200 * 5000 + end * 5000 + max_numb]; } if(end == start){ return 0; } if(end - start > max_numb){ return MIN_VAL; } if(end - start == max_numb){ int64_t ret = 0; int64_t counter = 0; for(int64_t i = start; i < end; i ++){ ret += __builtin_popcountll(counter) * pops[i]; counter ++; } return ret; } int64_t maxpow = 1; while(maxpow * 2 < max_numb){ maxpow *= 2; } int64_t ret = MIN_VAL; for(int i = start; i <= end; i ++){ int64_t sum = sums[i] - sums[end]; int64_t left = dp(pops, start, i, maxpow); int64_t right = dp(pops, i, end, max_numb - maxpow); if(left != MIN_VAL && right != MIN_VAL){ ret = max(ret, sum + left + right); } } if(__builtin_popcountll(max_numb) == 1){ lookup[start* 200 * 60 + end * 60 + log2(max_numb)] = ret; } if(max_numb < 5000){ lookup2[start* 200 * 5000 + end * 5000 + max_numb] = ret; } return ret; } int main(){ int64_t n; int64_t m; cin >> n; cin >> m; vector<int64_t> pops; pops.reserve(n); int64_t sum = 0; sums.push_back(0); for(int i = 0; i < n; i++){ int64_t tmp; cin >> tmp; sum += tmp; sums.push_back(sum); pops.push_back(tmp); } for(auto & cur: sums){ cur = sum - cur; } m++; cout << dp(pops, 0, pops.size(), m) << endl; } |
English