Codeforces 578B Or Game (前缀和 + 贪心)

Codeforces Round #320 (Div. 1) [Bayan Thanks-Round]

题目链接:B. "Or" Game

You are given \(n\) numbers \(a_1,?a_2,?...,?a_n\). You can perform at most \(k\) operations. For each operation you can multiply one of the numbers by \(x\). We want to make \(a_1 | a_2 | ... | a_n\) as large as possible, where \(|\) denotes the bitwise OR.

Find the maximum possible value of \(a_1 | a_2 | ... | a_n\) after performing at most \(k\) operations optimally.

Input

The first line contains three integers \(n\), \(k\) and \(x (1?≤?n?≤?200?000, 1?≤?k?≤?10, 2?≤?x?≤?8)\).

The second line contains \(n\) integers \(a_1,?a_2,?...,?a_n (0?≤?a_i?≤?10^9)\).

Output

Output the maximum value of a bitwise OR of sequence elements after performing operations.

Examples

input

3 1 2
1 1 1 

output

3

input

4 2 3
1 2 4 8

output

79

Note

For the first sample, any possible choice of doing one operation will result the same three numbers \(1, 1, 2\) so the result is \(1 | 1 | 2 = 3\).

For the second sample if we multiply \(8\) by \(3\) two times we‘ll get \(72\). In this case the numbers will become \(1, 2, 4, 72\) so the OR value will be \(79\) and is the largest possible result.

Solution

题意

给定 \(n\) 个数 \(a_1 ... a_n\),可以进行 \(k\) 次操作,每次可以给任意一个数乘上 \(x\),求 \(a_1 | a_2 | ... | a_n\) 最大为多少。

题解

贪心 前缀和

因为 \(x \ge 2\),因此一个数乘上 \(x\) 后二进制位数必然增加一位。

由于或运算是 \(0 | 1\) 时才会使答案增加,因此让 \(k\) 个 \(x\) 乘在同一个数上就行。

计算一下前缀和和后缀和,然后暴力枚举每一个数乘以 \(x^k\),找到最大值即可。

Code

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
typedef long long ll;

ll a[maxn], s1[maxn], s2[maxn];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll n, k, x;
    cin >> n >> k >> x;
    for(int i = 1; i <= n; ++i) {
        cin >> a[i];
        s1[i] = s1[i - 1] | a[i];
    }
    for(int i = n; i >= 1; --i) {
        s2[i] = s2[i + 1] | a[i];
    }
    ll ans = 0;
    ll tmp = x;
    for(int i = 2; i <= k; ++i) {
        tmp *= x;
    }
    for(int i = 1; i <= n; ++i) {
        ans = max(ans, s1[i - 1] | tmp * a[i] | s2[i + 1]);
    }
    cout << ans << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/wulitaotao/p/11616460.html

时间: 2024-10-08 15:57:41

Codeforces 578B Or Game (前缀和 + 贪心)的相关文章

[Codeforces 1295E]Permutation Separation(线段树+贪心)

[Codeforces 1295E]Permutation Separation(线段树+贪心) 题面 给出一个排列\(p_1,p_2,...p_n\).初始时你需要选择一个位置把排列分成左右两个.然后在两个序列间移动元素使得左边序列的所有元素都比右边的所有元素小.给出每个元素\(p_i\)从一个序列移动到另一个序列的代价\(a_i\). 分析 显然最后得到的序列是小的数在一边,大的数在另一边.设从值为\(i\)的元素处分开之后移动代价为\(ans_i\). 一开始假设所有数都移到右边序列,那么

Codeforces 583 DIV2 Robot&#39;s Task 贪心

原题链接:http://codeforces.com/problemset/problem/583/B 题意: 就..要打开一个电脑,必须至少先打开其他若干电脑,每次转向有个花费,让你设计一个序列,使得总花费最小. 题解: 就傻傻的走就好..从左走到右,再走回来,更新序列和答案就好. 代码: #include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #define MA

Codeforces 442C Artem and Array(stack+贪心)

题目连接:Codeforces 442C Artem and Array 题目大意:给出一个数组,每次删除一个数,删除一个数的得分为两边数的最小值,如果左右有一边不存在则算作0分.问最大得分是多少. 解题思路:首先将连续的a,b,c,a > b && c > b的情况将c掉,获得min(a,b)分,这样处理后数组变成一个递増再递减的序列,除了最大和第二大的取不到,其他数字均可以得分. 样例:4 10 2 2 8 #include <cstdio> #include

Codeforces 18D Seller Bob java大数+贪心

题目链接:点击打开链接 java: import java.math.BigInteger; import java.util.Scanner; public class Main { static int N = 5005; static BigInteger[] er = new BigInteger[N]; static BigInteger E = new BigInteger("2"); static int[] a = new int[N]; static int[] ma

Codeforces 437C The Child and Toy(贪心)

题目连接:Codeforces 437C The Child and Toy 题目大意:孩子有一个玩具,有n个部件组成,m条绳子组成,每条绳子连接两个部件.小孩比较顽皮,要将玩具拆成不可分割的部件,每次剪断一条绳子的代价是该绳子连接的两个部件的权值中较小的值.问说最小的总代价是多少. 解题思路:以为每条边都是要被剪断的,所以将节点按照代价值从大到小排序,每次拿掉权值大的点,与该点连接并且还未剪断的边均用另外点的权值. #include <cstdio> #include <cstring

Codeforces 437D The Child and Zoo(贪心+并查集)

题目链接:Codeforces 437D The Child and Zoo 题目大意:小孩子去参观动物园,动物园分很多个区,每个区有若干种动物,拥有的动物种数作为该区的权值.然后有m条路,每条路的权值为该条路连接的两个区中权值较小的一个.如果两个区没有直接连接,那么f值即为从一个区走到另一个区中所经过的路中权值最小的值做为权值.问,平均两个区之间移动的权值为多少. 解题思路:并查集+贪心.将所有的边按照权值排序,从最大的开始连接,每次连接时计算的次数为连接两块的节点数的积(乘法原理). #in

Codeforces 459E Pashmak and Graph(dp+贪心)

题目链接:Codeforces 459E Pashmak and Graph 题目大意:给定一张有向图,每条边有它的权值,要求选定一条路线,保证所经过的边权值严格递增,输出最长路径. 解题思路:将边按照权值排序,每次将相同权值的边同时加入,维护每个点作为终止点的最大长度即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 3

Codeforces Round #546 (Div. 2) D 贪心 + 思维

https://codeforces.com/contest/1136/problem/D 贪心 + 思维 题意 你面前有一个队列,加上你有n个人(n<=3e5),有m(m<=个交换法则,假如u在v相邻前面,那么u和v可以交换位置,问你是队列最后一个人的时候你最前可以换到前面哪里 题解 因为相邻才能换,所以最后一个换到前面一定是一步一步向前走,所以不存在还要向后走的情况 设最后一个为u,假设前面有一个能和u换位置的集合,那么需要将这些点尽量往后移动去接u 假设前面有一个不能和u换位置的集合S,

Codeforces 1334C - Circle of Monsters(差值取前缀和 / 贪心)

两种思路其实只差在写法上 看不懂的就直接看代码吧qwq 题面 题意 n只怪物围成一圈,每只怪物拥有体力a和爆炸伤害b 如果怪物 i 死亡(体力小于等于0),则与他相邻的下一只怪物将受到 b[i] 点伤害 (如果 i<n ,则下一只怪物为 i+1 :如果 i==n,则下一只怪物为 1) 如果相邻的下一只怪物不存在,则什么也不会发生 如果相邻的下一只怪物受到伤害后也死亡了,那么再下一只怪物会继续受到伤害(链式反应) 每次你能随便挑一只怪物开一枪,那只怪物的体力将会降低 1 点 问至少需要开多少枪才能