分析
有了位运算
想到的一定是贪心
因为答案从高位到低位贪心一定是最优的
那么我们可以考虑判断当前答案是否可行
设f[][]
表示当前到了i
个位置,分为了j
组是否成立
转移时枚举前一个位置,判断这一组是否为当前所需答案的超集即可
时间复杂度:
温馨提示:本题数据范围似乎有问题,需要达到左移60位才可过(只移50位不可过)
代码
//CF981D #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #define ll long long #define cl(x, y) memset((x), (y), sizeof(x)) #define rep(i, a, b) for(ll i = a; i <= b; i++) #define per(i, a, b) for(ll i = a; i >= b; i--) #define de(x) cerr << #x << " = " << x << " " #define inc_mod(x, y) x = ((x - y) % mod + mod) % mod #define add_mod(x, y) x = (x + y) % mod #define mul_mod(x, y) x = (x * y) % mod #define lowbit(x) (x & (-x)) #define inf 0x3f3f3f3f3f3f3f3f #define mod 998244353 #define rson (x << 1 | 1) #define lson (x << 1) using namespace std; const ll maxn = 55; bool f[maxn][maxn]; ll ans, total, limit; ll num[maxn], pre[maxn]; inline void file() { freopen(".in", "r", stdin); freopen(".out", "w", stdout); } signed main() { // file(); ios::sync_with_stdio(false); cin >> total >> limit; rep(i, 1, total) cin >> num[i], pre[i] = pre[i - 1] + num[i]; per(state, 60ll, 0ll) { cl(f, false); ll temp = ((1ll << state) | ans); f[0][0] = true; rep(i, 1ll, total) rep(k, 1ll, min(limit, i)) rep(j, 0ll, i - 1) { ll res = pre[i] - pre[j]; if((res & temp) == temp) f[i][k] |= f[j][k - 1]; } if(f[total][limit]) ans |= (1ll << state); } cout << ans << endl; // fclose(stdin); // fclose(stdout); system("pause"); return 0; }