2016大连站 hdu5973 Game of Taking Stones(Java高精度+威佐夫博弈+牛顿迭代)

本文探讨了威佐夫博弈的策略,利用牛顿迭代法求解高精度平方根,实现先手必胜的判断。通过分析两堆石子(a,b)的局面,运用牛顿迭代原理求解黄金分割比,判断先手是否必胜。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

威佐夫博弈裸题,两堆石子(a,b),1<=a,b<=1e100

问能否先手必胜,能输出1,否则输出0

思路来源

https://blog.csdn.net/Li_Yufeng/article/details/78044019?utm_source=blogxgwz9 牛顿迭代的题解

https://blog.csdn.net/Young_12138/article/details/71074765 二分答案的题解

https://www.cnblogs.com/zwfymqz/p/8469863.html 威佐夫博弈原理

https://blog.csdn.net/xiaoyu714543065/article/details/8656177 高精度 小数位数异常

https://www.zhihu.com/question/20690553/answer/146104283 牛顿迭代原理

https://zhuanlan.zhihu.com/p/64728645?utm_source=qq&utm_medium=social&utm_oi=1009214313768173568 Leetcode牛顿迭代代码

题解

威佐夫博弈,

当局面为(int)(y-x)*\frac{\sqrt{5}+1}{2}==x(x<y)时,先手必败,否则先手必胜

牛顿迭代搞出sqrt开根函数,求出\frac{\sqrt{5}+1}{2},用高精度的函数判断即可

关于牛顿迭代

一般用于求二次方程的解,适用函数有局限性,

原理:https://www.zhihu.com/question/20690553/answer/146104283 

基础应用:https://zhuanlan.zhihu.com/p/64728645?utm_source=qq&utm_medium=social&utm_oi=1009214313768173568

此处用于求x^2=a,求x的过程,令f(x)=x^2-a,则f'(x)=2x

先找到零点右侧的解(一定要选好初值),则每次向左迭代,直到零点,

只能从一侧向零点迭代,选左侧也可,

本次取的横坐标为x_{n},则下一次取的横坐标x_{n+1}=x_{n}-\frac{f(x_{n})}{f'(x_{n})}

二次方程这里化简得,x_{n+1}=\frac{x_{n}+\frac{a}{x_{n}}}{2}

简易代码

以下代码,用于求x^2=a的x的整数部分

来自https://zhuanlan.zhihu.com/p/64728645?utm_source=qq&utm_medium=social&utm_oi=1009214313768173568

class Solution {
    public int mySqrt(int x) {
        if(x == 1 || x == 0)
            return x;
        int a = x >> 1;
        while(a > x / a){
            a = (a + x/a) / 2;
        }
        return a;
    }
}

代码

import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;

public class Main {
	public static BigDecimal sqrt(BigDecimal a, int d) {
		BigDecimal one = new BigDecimal("1");
		BigDecimal two = new BigDecimal("2");
		BigDecimal eps = one.divide(new BigDecimal(10).pow(d));
		if (a.abs().compareTo(eps) < 0)
			return new BigDecimal("0");
		BigDecimal dif = a.subtract(one);
		if (dif.abs().compareTo(eps) < 0)
			return one;
		BigDecimal ans = a.divide(two, d, BigDecimal.ROUND_HALF_EVEN);
		while (ans.multiply(ans).subtract(a).compareTo(eps) > 0) {
			ans = (ans.add(a.divide(ans, d, BigDecimal.ROUND_HALF_EVEN)));
			ans = ans.divide(two);
		}
		return ans;
	}

	public static void main(String[] args) {
		Scanner cin = new Scanner(new BufferedInputStream(System.in));
		PrintWriter cout = new PrintWriter(System.out);
		BigDecimal a, b, c, gold;
		BigDecimal one = new BigDecimal("1");
		BigDecimal two = new BigDecimal("2");
		BigDecimal five = new BigDecimal("5");
		BigDecimal eps = one.divide(new BigDecimal("10").pow(50));
		gold = sqrt(five,100);
		gold = gold.add(one).divide(two);
		while (cin.hasNext()) {
			a = cin.nextBigDecimal();
			b = cin.nextBigDecimal();
			if (a.compareTo(b) > 0) {
				c = a;
				a = b;
				b = c;
			}
			b = b.subtract(a);
			b = b.multiply(gold);
			b = b.setScale(0,RoundingMode.FLOOR);
			if (b.subtract(a).abs().compareTo(eps)<0)
				System.out.println("0");
			else
				System.out.println("1");
		}
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小衣同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值