CJOJ 取石块儿解题报告

【问题描述】

小 L 和小 T 进行取石块儿游戏,给定一个整数 n 表示石块儿总数,给定一个整数 k 表
示每次最多能拿走的石块儿数量,小 L 先手,每次能拿走 1~k 个石块儿,他们中总会有一
个人最后拿走 s 块儿石块儿,使得剩余石块儿数量为 0,则最后一个拿走剩下石块儿的人获
胜,另外一个人失败。
小 T 非常聪明,小 L 绝顶(秃子(逃))聪明,请判断小 T 是否能取胜。

【输入】

第一行一个整数 T 表示数据组数,接下来 T 行每行两个整数 n,k 意义为描述所给。

【输出】

对于每组数据,输出"YES"或者"NO"(不带引号),代表小 T 是否能够获胜。
【输入输出样例】
Input
2
2 1
10 4
Output
YES
YES

题解

倒过来想 考虑最后一步
考虑最让小L绝望的情况,那就是无论如何都只能剩下k块以内的石头数,即k+1块,如果只剩k+1块,那么无论这个人怎么取,另外一个人都可以取完;
也就是说,谁能让石块剩余k+1块,谁就是赢家,同理,为了让石块剩余k+1块,只要取到k+1+k+1,就一定能取到k+1;
所以,谁拿到了k+1的倍数,谁就是赢家
所以只要判断出n与k+1的关系,就能在开局判断结果(当然是两个人都足够聪明的情况)
若n为k+1的倍数,先手肯定怎么都赢不了(只要后手没有飘)

代码

#include <cstdio>
#define ll long long
#define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
inline unsigned ll read(){
    unsigned ll x=0;char c=getchar();
    while (c<'0'||c>'9') c=getchar();
    while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x;
}
unsigned ll n,k;

void init(){
    n=read(),k=read();
}

void doit(){
    if (n-n/(k+1)*(k+1)) puts("NO");//n-n/(k+1)*(k+1)=n%(k+1),前者跑得比后者快一点点
    else puts("YES");
}

signed main(){
    file("tstones");
    int T=read();
    while (T--){
        init();
        doit();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ancer/p/11294898.html