2016 年华南师范大学 ACM 新生决赛 - 重现(Oyk剪纸)

题目描述
Oyk 又和 Zlm 剪纸了。因为以往的剪纸都是一个方向的,他们决定换个方式。
把一张矩形纸分割为 a*b 的网格,每次可以剪去 n 个格子以内组成的矩形。
Oyk 希望能剪到最后一个格子,那么他应该先剪还是后剪?
图片崩了...(凑活着先。。。)

如 n=5 时,下列方案中 1,2,5 为可行方案,3 不是(因为它不是个矩形),4 也不是(因为由 6>5 个格子组成)
注意,剪完之后如果纸断开了,可以任选一部分剪,如同它们没有断开一样,只是不可能同时剪到其中的多个部分;剪出来的部分就扔了,不再动。

输入

输入有多组(少于1000组)数据,处理到文件尾。每行有三个数字,a,b和 n(均为小于10000的正整数),由空格隔开。

输出

对每个样例。输出 1 如果应该先走,否则输出 2。

样例输入

1 3 1
1 3 3

样例输出

1
1

提示

1 3 1 中,不管剪哪一个格子,总会剩下两个,Zlm 再剪一个剩下一个,Oyk 能剪到最后一个。

1 3 3 中,Oyk 可以一次把整个纸剪了,Oyk 还是能剪到最后一个。
题解:
我一开始看到这道题以为到真是道经典博弈论的题目,然后尝试去套Nim博弈结果一直解不通,后面看了题解才恍然大悟这是到规律题(哭崩...),和2017年新生赛中几道题一样。
推荐先思考的经典问题:
(一)一个圆桌上放硬币,先放满(剩余空间不能再容纳)为胜,先手怎么放才能获胜;
(二)变种:一个直径d圆桌放直径p圆盘,先放满为负,问先手能不能赢;
(三)一维剪纸:一条长纸带划为n格;一条环形纸带划为n格
首先观察题目给的条件,发现剪纸是个对称的,也就是说先手的人在左侧剪去格子,后手一定能在右侧剪去相同的格子,所以先手获胜的情况是去减中间的格子使得后手的人面临这种情况。由于剪纸具有对称性我们考虑几种特殊情形(先手获胜策略):
(一)1×1的剪纸,先手剪去中间一个格子
(二)1×2的剪纸,先手剪去中间两个格子
(三)2×2的剪纸,先手剪去中间三个格子
2×1与1×2一致,所以我们会发现当a与b同奇的时候只需剪去一个格子,一奇一偶的时候只需剪去2个格子,同偶的时候只需剪去4个格子。(画出剪纸是1×3,2×3,3×3,4×4感受一下就可以理解了)
附上自己的AC代码

#include 
#include 
using namespace std;

int main()
{
    int a,b,n;
    while(scanf("%d%d%d",&a,&b,&n)!=EOF){
        if((a%2!=0&&b%2!=0&&n>=1)||(a%2!=0&&b%2==0&&n>=2)||(a%2==0&&b%2!=0&&n>=2)||(a%2==0&&b%2==0&&n>=4))
            printf("1\n");
        else
            printf("2\n");
    }
    return 0;
}

附上zyj大佬的AC代码(现在还没看到其中的<<操作,如果有理解的可以在评论区讨论一下)(蒟蒻的请教)
时间复杂度O(1)

#include 

int main() {
    int a, b, n;
    while (~scanf("%d%d%d", &a, &b, &n))
        puts(4 >> (a % 2 + b % 2) > n ? "2" : "1");
    return 0;
}

附上zyj的解题博客链接
http://www.cnblogs.com/BlackStorm/p/SCNUCPC_2016_For_Freshman_Final_Solution.html

你可能感兴趣的:(2016 年华南师范大学 ACM 新生决赛 - 重现(Oyk剪纸))