HDU 5973 Game of Taking Stones 博弈+高精度

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5973

题意:全裸的威佐夫博弈,但是输入的两个数长度长达100位

思路:能在比赛现场做出这道题,运气还是占了绝大多数,比赛前无聊拿走了去年朱神和csy的板子,里面恰好就有对java高精度的操作,队友的提醒也很重要,在比赛结束前的一个小时ac了。

首先对于普通威佐夫博弈,很容易写出这样的C++代码:

#include
#include
#include
#include
using namespace std;
const double GOLD=(sqrt(5)+1)/2.;
int main(){
    int a,b,c;
    while(~scanf("%d%d",&a,&b)){
        if(a>b) swap(a,b);
        c=floor(b-a)*GOLD;
        if(c==a) puts("0");
        else puts("1");
    }
}

我们一开始用java写出了类似的高精度代码,可是一直wa,后来sjt说了关键的一句话,数据范围是10的100次方,还有小数乘法,这时我明白了一直wa的原因是我们没有吧黄金分割率精确到小数点后100位,于是我用二分法去把根号5精确到了小数点后的100位,然后就莫名的ac了……

import java.math.BigDecimal;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        BigDecimal TWO = BigDecimal.valueOf(2);
        BigDecimal FIVE = BigDecimal.valueOf(5);

        BigDecimal EPS = new BigDecimal("-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
        //System.out.println(EPS);
        BigDecimal l = new BigDecimal("2.2360679774997"), r = new BigDecimal("2.2360679774998");
        BigDecimal m = null;

        while(l.subtract(r).compareTo(EPS)<0){
            m = l.add(r).divide(TWO);
            if(m.multiply(m).subtract(FIVE).abs().compareTo(EPS.abs())<0) break;
            if(m.multiply(m).subtract(FIVE).compareTo(EPS)<0) l = m;
            else r = m;
        }
        //System.out.println(m);

        BigDecimal GOLD = m.add(BigDecimal.ONE).divide(TWO);
        //System.out.println(GOLD);
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            BigDecimal a = sc.nextBigDecimal(), b = sc.nextBigDecimal();
            if(a.compareTo(b)>0){
                BigDecimal t = a;
                a = b;
                b = t;
            }
            //System.out.println(a);
            //System.out.println(b);
            BigDecimal c = b.subtract(a).setScale(0,BigDecimal.ROUND_FLOOR).multiply(GOLD);
            c = c.setScale(0, BigDecimal.ROUND_FLOOR);
            if(a.equals(c)) System.out.println("0");
            else System.out.println("1");
        }
    }
}

这题c++也可以做,就是计算公式的时候先把要运算的数先乘进根号里,然后用二分的方法来开根号,求出整数部分,再比较结果。
因为写起来比较麻烦,就先不写了。

你可能感兴趣的:(高精度)