BZOJ 1982 Spoj 2021 Moving Pebbles 博弈论

题目大意:给定n堆石子,每次可以选择一堆石子,拿走任意个,然后将堆中剩余石子移动任意个到任意一些堆里,不能操作者为输,求是否先手必胜
必败状态为: n 为偶数,且将石子数相同的堆两两配对可以配成 n2
例如:
6
1 1 4 4 5 5 
这就是一个先手必败的初始状态
证明:
首先证明这个状态是必败的
由于堆可以两两配对,因此无论先手做什么,后手都可以对另一个堆做同样的事情,故先手必败
对于一种其他状态,先手可以用一步将状态变为必败状态,故其他状态下先手必胜
如果初始有奇数堆石子,那么先手可以将最小的堆和第二小的堆配对,第三小的堆和第四小的堆配对,…,然后用最大的堆填补差值,显然一定能填补上;
如果初始有偶数堆石子,那么先手可以将最大的堆和最小的堆配对,第二小的堆和第三小的堆配对,第四小的堆和第五小的堆配对,..,用最大的堆多出来的部分填补差值,显然也一定能填补上
故其他状态先手必胜

#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
int n;
char s[M];
string a[M];
int main()
{
    int i;
    cin>>n;
    if(n&1)
        return cout<<"first player"<<endl,0;
    for(i=1;i<=n;i++)
    {
        scanf("%s",s+1);
        a[i]=s+1;
    }
    sort(a+1,a+n+1);
    for(i=1;i<=n;i+=2)
        if(a[i]!=a[i+1])
            return cout<<"first player"<<endl,0;
    return cout<<"second player"<<endl,0;
}

你可能感兴趣的:(博弈论,bzoj,BZOJ1982)