牛客 Wannafly挑战赛24 A石子游戏(思维)

题目链接
链接:https://www.nowcoder.com/acm/contest/186/A
来源:牛客网

Alice和Bob在玩游戏,他们面前有n堆石子,对于这些石子他们可以轮流进行一些操作,不能进行下去的人则输掉这局游戏。
可以进行两种操作:
1. 把石子数为奇数的一堆石子分为两堆正整数个石子
2. 把两堆石子数为偶数的石子合并为一堆
两人都足够聪明,会按照最优策略操作。现在Alice想知道自己先手,谁能最后赢得比赛。
输入描述:
第一行一个正整数n。(1<=n<=104)
接下来第二行n个正整数表示每堆石子的数量。每堆石子不超过105个。
输出描述:
Alice或者Bob,表示谁能最后赢得游戏。
示例1
输入
复制
3
3 2 2
输出
复制
Alice
说明
Alice只要现将两个石子数量为2的堆合并为一堆4个石子,Bob就只能把3分为两堆1和2,接下来Alice只要将2和4合并,Bob输掉了这局游戏。

题解
很明显问题的核心在大于1的奇数的处理上,我们先从特殊的考虑,3只能分成1和2,然后2可以和另外的偶数合并一次,5可以分成1和4(次数为2) 或 2和3(次数为4),然后我们可以发现奇数的分解带来的次数增加都是偶数次的(这里有一个前提就是已存在偶数,处理这里的方法就是最后统计的时候减1)
然后就是特殊情况的考虑,假如全是1,那么先手必败

#include 
using namespace std;
#define rep(i,a,n) for (int i=a;i
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
//head
int n;
int a[20005];
int main(int argc, char const *argv[])
{
    cin>>n;
    int t = 0;
    int t2 = 0;
    rep(i,0,n)
    {
        cin>>a[i];
        if(a[i] % 2 && a[i] != 1)
            t++;
        if(a[i] % 2 == 0)
            t2++;
    }
    t = t * 2 + (t2-1);
    if(t < 0)//全是1
        t = 0;
    if(t % 2)
        cout<<"Alice"<else
        cout<<"Bob"<return 0;
}

你可能感兴趣的:(acm,思维,博弈)