F. Stone 题解(对称博弈)

题目链接

题目思路

这个写法感觉有点天才,当作记录一下吧

其实越复杂的博弈好像其实最后的结论越简单?

放下官方题解

题意:轮流拿石头,每个人先确定一个上次选的数字的因数

s,然后再选择若干堆同时拿走 s 个石头,问先手有多少种

第一步的方案数使得先手必胜。

考虑这样一种局面:存在某堆石头的数量是奇数。那不管是

先手还是后手,选择 s = 1(奇数) 先把所有堆变成偶数个,

然后对手也只能 s = 1(奇数),模仿对面拿法即可。

换言之,如果所有堆都是偶数,则不管是谁都不能选 s 为奇

数,否则变成前面一种情况,对手必胜。即 s 只能为偶数,

此时堆数量 / = 2,转化为相同的问题。

那么一直除以 2,总会在某个时候出现某个石头堆有奇数

个,转换为前面的局面。

此时答案为 (最小奇数+1)/2。

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=1e6+5,inf=0x3f3f3f3f,mod=998244353;
const double eps=1e-4;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n;
int a[maxn];
signed main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    while(1){
        int mi=inf;
        for(int i=1;i<=n;i++){
            if(a[i]%2==1){
                mi=min(mi,a[i]);
            }
        }
        if(mi!=inf){
            printf("%d\n",(mi+1)/2);
            break;
        }
        for(int i=1;i<=n;i++){
            a[i]/=2;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/hunxuewangzi/p/15594844.html