2019西北工业大学程序设计创新实践基地春季选拔赛(重现赛)-G(DP)

Chino with Train to the Rabbit Town

题目链接:https://ac.nowcoder.com/acm/contest/553/G
感谢大佬博客的指点:https://www.cnblogs.com/FrankChen831X/p/10666916.html

题意

给定n,k,(1<=n<=5e5)然后给出n个数ai(1<=ai<=1e5),问按顺序从1…n分组,最多能有多少个组的异或和为k。

输入描述:第一行是两个数n, k,接下来一行是n个数ai

输出描述:题目中要求的答案

示例:
输入:
3 1
1 2 3
输出:
2

思路

首先我们需要知道 a ^ b ^ b = a, 若有 a1 ^ a2 ^ a3 ^ a4 ^ a5 ^ k = a1 ^ a2 ^ a3,则有 a4 ^ a5 = k。
DP思路,我们可以用 DP[ i ] 表示到第 i 个人的时候最多有多少组的异或和为k,下面考虑状态转移方程,DP[ i ] 的取值有两种情况。第一种:当前 ai 无法与 ai 的前面若干个意愿值异或和为k,此时DP[ i ]=DP[ i -1 ]。第二种:当前 ai 可以与ai前若干个意愿值异或和为k,即存在 j <i , a(j+1) ^ a(j+2) ^ …^ a(i) =k,DP[ i ] =max(DP[ i - 1 ] ,DP[ j ] + 1 )。如何知道是否存在这个 j 呢?我们可以用sum记录ai的异或前缀和,然后设置一个pre数组记录各sum值对应的最后一个元素下标,这样pre[ sum^k ] 即为 j 。若不存在,pre数组为默认值-1,下面看代码。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MAXN 500005
int DP[MAXN],sum;
int pre[MAXN];
int main()
{
	std::ios::sync_with_stdio(false);  
	int n,k;
	cin>>n>>k;
	memset(pre,-1,sizeof(pre));
	pre[0]=0;
	for(int i=1;i<=n;++i){
		int a;
		cin>>a;
		sum^=a;
		if(pre[sum^k]!=-1){
			DP[i]=max(DP[i-1],DP[pre[sum^k]]+1);
		}
		else DP[i]=DP[i-1];
		pre[sum]=i;
	}
	cout<<DP[n]<<endl;
	
 } 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值