9
22
2015
1

4245: [ONTAK2015]OR-XOR

4245: [ONTAK2015]OR-XOR

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 137  Solved: 80
[Submit][Status][Discuss]

Description

给定一个长度为n的序列a[1],a[2],...,a[n],请将它划分为m段连续的区间,设第i段的费用c[i]为该段内所有数字的异或和,则总费用为c[1] or c[2] or ... or c[m]。请求出总费用的最小值。
 

 

Input

第一行包含两个正整数n,m(1<=m<=n<=500000),分别表示序列的长度和需要划分的段数。
第一行包含n个整数,其中第i个数为a[i](0<=a[i]<=10^18)。
 

 

Output

输出一个整数,即总费用的最小值。
 

 

Sample Input

3 2
1 5 7

Sample Output

3

HINT

 

第一段为[1],第二段为[5 7],总费用为(1) or (5 xor 7) = 1 or 2 = 3。


 

 

Source

    我们可以贪心的从高位向低位考虑。。。先求出前缀异或值。。对于一个二进制位如果他可以为0。。那么需要至少有m个的前缀异或值为0并且n的位置上必须为0。。然后把这个位上值为1的位置强制赋为不可取。。如果没有m个位置为0。。就把答案增加。。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
bool vis[500010];
ll ans=0,a[500010],n,m,cnt,f;
int main(){
	scanf("%lld%lld",&n,&m);
	for (int i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]^=a[i-1];
	for (int i=62;i>=0;i--){
		f = 1;
		if ((a[n]>>i)&1) f = 0;
		else {
			cnt = 0;
			for (int j=1;j<n;j++)
				if (!vis[j] && (((a[j]>>i)&1)==0)) cnt++;
			if (cnt<m-1) f = 0;
		}
		if (f) {for (int j=1;j<n;j++) if ((a[j]>>i)&1) vis[j] = 1;}
		else ans|=(1ll<<i);
	}
	printf("%lld",ans);
}
Category: BZOJ题解 | Tags: | Read Count: 593
Avatar_small
cleaning services du 说:
2020年2月24日 16:19

Office environment cleaning products are quite low for cost compared to the total value of using the services of conventional maintenance methods. The provider is notable mainly a result of quality for services rendered, which come up with the work place professional together with organized.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com