您的位置:首页 > 其它

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

2019-04-08 23:26 211 查看

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐