“纽劢科技杯”第十六届同济大学程序设计竞赛暨上海邀请赛同步赛 J-张老师的游戏...

 

传送门

 

题目描述

 

    在空闲时间,张老师习惯性地和菜哭武玩起了取石子游戏,这次的游戏规则有些不同,在他们面前有n堆石子,其中,第i堆石子的个数为a[i],现在制定规则如下:
    从张老师开始,两个人轮流取石子,每次可以从任意一堆中取走x个石子,其中x必须严格小于这堆石子的总数并且能够被这堆石子的个数整除,谁先无法继续取走石子就算失败!
    例如,只有一堆石子,个数为6,张老师首先可以取走的石子个数为1,2或者3个。
    现在给定n堆石子每一堆的石子数,张老师希望你帮他确定在双方最优策略下他能否赢得游戏。

链接:https://acm.nowcoder.com/acm/contest/637/J
来源:牛客网

输入描述:

 

    第一行一个整数n(1<=n<=100,000)
    第二行n个整数,分别代表每一堆石头的个数,保证所有数据为小于等于10

9

的正整数

 

输出描述:

 

输出一行,Win或者Lose,表示张老师能否获得胜利

 

示例1

输入

3
2 2 1

输出

Lose

 

示例2

 

输入

2
2 9

 

输出

 

Win

博弈,后继状态是$n-a_{i}$
$a_{i}$表示除n外的其他因子
打表发现SG函数是该数质因子里有多少个2

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1010;
int SG[maxn], S[maxn], f[maxn];

void getSG(int n) {
    S[1] = 0;
    for (int i = 2; i <= n; i++) {
        memset(S, 0, sizeof(S));
        int cnt = 0;
        int temp = i;
        f[cnt++] = 1;
        for (int j = 2; j < temp; j++) {
            if (temp % j == 0) {
                f[cnt++] = j;
            } 
        }
        sort(f, f + cnt);
        for (int j = 0; j < cnt; j++) {
            S[SG[i-f[j]]] = 1;
        }
        for (int j = 0; ; j++) {
            if (!S[j]) {
                SG[i] = j;
                break;
            }
        }    
    }   
}
int sg(int x) {
    int ret = 0;
    while (x % 2 == 0) ret++, x /= 2;
    return ret;
}

int main() {
   // getSG(1000);
   // for (int i = 1; i <= 500; i++) cout << SG[i] << ",";
    int n;
    scanf("%d", &n);
    int flag = 0;
    for (int i = 0; i < n; i++) {
        int x;
        scanf("%d", &x);
        flag ^= sg(x);
    }
    if (flag) puts("Win");
    else puts("Lose");
    return 0;
}
View Code
 
       

 

 

转载于:https://www.cnblogs.com/Mrzdtz220/p/10781370.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值