The 16-th BIT Campus Programming Contest - Online Round--Easy Nim

Problem - C - Codeforceshttps://codeforces.com/gym/103401/problem/C题目大意为每人每轮最多拿m张牌,谁先取完n张牌谁胜;后手有k张魔法牌,每张魔法牌上写有数字(这里把数字放在c数组里)可以将修改上限变为牌上的数字,发动魔法牌时不能取牌。

拿牌(取石子游戏)有一个必胜策略是将n张牌的剩余个数拿到(m+1)的倍数

(先手不能发动魔法牌,所以只是个无情的拿(m+1)的倍数的机器人)

例如:10张牌,每人最多拿3张,这样的话先手必胜,下面的过程着重看先手拿剩几张牌

先手拿1张,剩余9张,后手拿3张,剩余6张;

先手拿2张,剩余4张,后手拿1张,剩余3张;

先手拿3张,剩余0张,先手获胜;

先手的赢面很大,除了n=(m+1)的倍数,后手必胜的情况。

回到这道题,

        显然,当m>=n时,先手必胜;

        当n=(m+1)的倍数,后手必胜的情况时,先手不能发动魔法牌,所以不能扭转局面,于是先手必败;

        当n!=(m+1)时,先手拿牌拿到n=n-n%(m-1),这时后手有两种情况获胜。

        第一种魔法牌中有(m+1)的倍数刚好是(c[i]+1)的倍数,后手发动牌技能(同时n>c[i]),这样就后手必胜了,也就是说判断条件为只要n大于(c[i]+1)和(m+1)的最小公倍数,那么无论先手怎么取,后手都能控制到(c[i]+1)的倍数;

if(n>(c[i]+1)*(m+1)/__gcd(c[i]+1,m+1)){
    cout<<"zyw";
}

        第二种是魔法牌的组合,魔法牌中有(c[i]+1)的倍数刚好是(c[j]+1)的倍数,后手先发动c[i](n>c[i]),之后n=n-n%(c[i]+1),这时n是c[i]+1的倍数,然后后手发动c[j](n>c[j]),如果这时n也是c[j]+1的倍数,那么后手就获胜。

if((c[i]+1)*(c[j]+1)/__gcd(c[i]+1,c[j]+1)<=(n-min(n%(c[i]+1),n%(c[j]+1)))){
    cout<<"zyw";
}

如果这些情况都没有,那么先手必胜。

贴一个参照了cf上的解法的代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
     int c[1010];
     int n,m,k;
     cin>>n>>m>>k;
     for (int i=0;i<k;i++)cin>>c[i];
     if (n%(m+1)==0){//because lyw couldn't use card
          cout << "zyw";
          return 0;
     }
     if (n<=m){//first win
          cout << "lyw";
          return 0;
     }//until m+1 mod eg.24 12 1 1 ---second win-
     n-=n%(m+1);//so when m+1 ,and (m+1)mod c[i]==0 second will win
     for (int i=0;i<k;i++){
          if (c[i]<=n&&n%(c[i]+1)==0){
              cout<<"zyw";
              return 0;
          }
     }
     for (int i=0;i<k;i++){
          for (int j=i+1;j<k;j++){
               long long x =(long long)(c[i]+1)*(c[j]+1)/__gcd(c[i]+1,c[j]+1);//最大公约数
               if(x<=(long long)n-min(n%(c[i]+1),n%(c[j]+1))){
                    cout<<"zyw";
                    return 0;
               }
          }
     }
     cout<<"lyw";
     return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值