Playing games —— 基本dp+滚动数组

链接:https://www.nowcoder.com/acm/contest/146/H
来源:牛客网

题目描述
Niuniu likes playing games. He has n piles of stones. The i-th pile has ai stones. He wants to play with his good friend, UinUin. Niuniu can choose some piles out of the n piles. They will play with the chosen piles of stones. UinUin takes the first move. They take turns removing at least one stone from one chosen pile. The player who removes the last stone from the chosen piles wins the game. Niuniu wants to choose the maximum number of piles so that he can make sure he wins the game. Can you help Niuniu choose the piles?

输入描述:
The first line contains one integer n (1 ≤ n ≤ 500000), which means the number of piles.
The second line describes the piles, containing n non-negative integers, a1 a2 … an, separated by a space. The integers are less than or equal to 500000.

输出描述:
Print a single line with one number, which is the maximum number of piles Niuniu can choose to make sure he wins. If Niuniu cannot always win whatever piles he chooses, print 0.
示例1
输入
复制
8
1 9 2 6 0 8 1 7
输出
复制
7
说明
Niuniu can choose the piles {1,9,6,0,8,1,7} to make sure he wins the game.

赛后看了别人的题解才会,刚开始不知道被谁榜带偏了,所有人都在做这道题,呵呵,没多少做出来的。
我们可以知道,若一堆数的异或和为0,先手一定会打破这种平衡,后手则可以修补这种平衡,所以在异或为0的情况下,后手胜,之后就是通过dp来找出最少需要去掉几个数才能使异或和为0;

#include<bits/stdc++.h>
using namespace std;
#define maxn 600005
#define inf 0x3f3f3f3f
int dp[2][maxn],vis[maxn];
vector<int>vec;
int main()
{
    int n;
    scanf("%d",&n);
    int a;
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a);
        if(!vis[a])
            vec.push_back(a);
        vis[a]=1;
        dp[0][a]=1;
        sum^=a;
    }
    if(sum==0)
        printf("%d\n",n);
    else if(vis[sum])
        printf("%d\n",n-1);
    else
    {
        int flag=0;
        for(int i=0;i<vec.size();i++)
            if(vis[sum^vec[i]])
            {
                flag=1;
                break;
            }
        if(flag)
            printf("%d\n",n-2);
        else
        {
            int pos=0;
            memset(dp,inf,sizeof(dp));
            dp[0][0]=0;
            for(int i=0;i<vec.size();i++)
            {
                pos^=1;
                for(int j=0;j<=maxn;j++)
                {
                    if(dp[pos^1][j]>=inf)
                        continue;
                    dp[pos][j]=min(dp[pos][j],dp[pos^1][j]);
                    dp[pos][j^vec[i]]=min(dp[pos^1][j]+1,dp[pos][j^vec[i]]);
                }
            }
            printf("%d\n",max(n-dp[pos][sum],0));
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/81591557