[hdu 5973 Game of Taking Stones] Wythoff Game+大数运算
题目链接:[hdu 5973 Game of Taking Stones]
类似题目:[51Nod 1185 威佐夫游戏 V2]
题意描述:有2堆石子。两个人轮流拿。每次可以从一堆中取任意个或从2堆中取相同数量的石子,但不可不取。拿到最后1颗石子的人获胜。假设两个人都按照最优的策略取石子。给出2堆石子的数量,问先手是否能赢得比赛。 每堆石子的大小
≤10100
。
解题思路:典型的Wythoff Game[威佐夫博弈],满足黄金分割。
根据Wythoff 博弈定理:当且仅当 a=⌊k∗5√+12⌋,b=a+k 时,先手失败;否则后手失败。
由于题目给定的石子数目巨大,所以不能用浮点数直接进行运算。在我的另外一篇博客《 [51Nod 1185 威佐夫游戏 V2]Wythoff Game+乘法模拟 》中,石子范围是
1018
, 我采用的是乘法模拟的方法。
在这个题目里面数据更大。乘法模拟起来就麻烦得多了。所以不妨直接用Java搞。关键是算
5√
。Java的BigDemical类中没有开根号的函数。需要自己手写二分实现开根号。
tips:5√+12=1.6180339887498948482045868343656... ,黄金分割率就是 0.6180339887498948482045868343656... 。
import java.math.BigDecimal;
import java.util.Scanner;
public class Main {
static BigDecimal sqrt_five, G;
static BigDecimal two, five;
public static void init() {
two = new BigDecimal(2);
five = new BigDecimal(5);
BigDecimal low, high, mid;
low = new BigDecimal(0);
high = new BigDecimal(5);
mid = new BigDecimal(0);
for(int i = 0; i < 1000; i++) {
mid = low.add(high).divide(two);
if(mid.multiply(mid).compareTo(five) > 0) high = mid;
else low = mid;
}
sqrt_five = mid;
// G = (sqrt(5) + 1) / 2;
G = sqrt_five.add(BigDecimal.ONE).divide(two);
}
public static void main(String[] argv) {
BigDecimal a, b, c, left, right;
init();
Scanner input = new Scanner(System.in);
while (input.hasNext()) {
a = input.nextBigDecimal();
b = input.nextBigDecimal();
if (a.compareTo(b) > 0) {
c = a;
a = b;
b = c;
}
left = b.subtract(a).multiply(G);
right = a;
// 向下取整。统一精度。
left = left.setScale(0, BigDecimal.ROUND_DOWN);
right = right.setScale(0, BigDecimal.ROUND_DOWN);
if(left.compareTo(right) == 0) System.out.println("0");
else System.out.println("1");
}
return;
}
}