题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2177
题意:不光求出胜负,还要求出胜利的话第一次可以怎么取。
先考虑两边同时取的情况,差值不变,根据差值计算出取完后两堆中较小的值,若这个计算出的值比没取之前的较小值小则可以取,然后加上差值就是取完后较大的堆的值。
如果在一堆中取,则只需取较大的那堆即可,至于为什么我还没想好怎么解释.....然后枚举取的数量进行判断即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
int main() {
int n, m;
while(~scanf("%d %d", &n, &m) , m + n) {
if(n > m) {
swap(n, m);
}
int k = m - n;
int tmp = (1.0 * k * (sqrt(5) + 1) / 2);
if(tmp == n) puts("0");
else if(tmp < n) { //可以两堆同时取的情况
puts("1");
printf("%d %d\n", tmp, m - (n - tmp));
int i;
for(i = 1; i <= m; i++) { //枚举取的数量,判断是否为奇异局势
k--;
if(k < 0) { //注意k正负的处理
tmp = (1.0 * (-k) * (sqrt(5) + 1) / 2);
if(m - i == tmp) { //此时m - i成为了较小堆
printf("%d %d\n", m - i, n);
}
}
else {
tmp = (1.0 * k * (sqrt(5) + 1) / 2);
if(tmp == n) {
printf("%d %d\n", n, m - i);
}
}
}
}
else { //此时只能从较大堆取
puts("1");
int i;
for(i = 1; i <= m; i++) {
k--;
tmp = (1.0 * k * (sqrt(5) + 1) / 2);
if(tmp == n) {
printf("%d %d\n", n, m - i);
}
}
}
}
return 0;
}