思路:能在比赛现场做出这道题,运气还是占了绝大多数,比赛前无聊拿走了去年朱神和csy的板子,里面恰好就有对java高精度的操作,队友的提醒也很重要,在比赛结束前的一个小时ac了。
首先对于普通威佐夫博弈,很容易写出这样的C++代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
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++也可以做,就是计算公式的时候先把要运算的数先乘进根号里,然后用二分的方法来开根号,求出整数部分,再比较结果。
因为写起来比较麻烦,就先不写了。