您的位置:首页 > 其它

[51Nod 1185 威佐夫游戏 V2]Wythoff Game+乘法模拟

2016-10-16 20:37 507 查看

[51Nod 1185 威佐夫游戏 V2]Wythoff Game+乘法模拟

题目链接[51Nod 1185 威佐夫游戏 V2]

题意描述:有2堆石子。A B两个人轮流拿,A先拿。每次可以从一堆中取任意个或从2堆中取相同数量的石子,但不可不取。拿到最后1颗石子的人获胜。假设A B都非常聪明,拿石子的过程中不会出现失误。给出2堆石子的数量,问最后谁能赢得比赛。

例如:2堆石子分别为3颗和5颗。那么不论A怎样拿,B都有对应的方法拿到最后1颗。

注意:这个题目每堆石子的数目是在[1,1018]范围内。

解题思路:根据Wythoff 博弈定理:当且仅当a=⌊k∗5√+12⌋,b=a+k时,先手失败;否则后手失败。由于题目给定的石子数目很大,所以不能用浮点数直接进行运算。[tips:5√+12=1.6180339887498948482045868343656...],这里用到了乘法模拟的方法,来增大精度。

这题还有一个Java大数的做法, 请参考另外一篇博客《 [hdu 5973 Game of Taking Stones] Wythoff Game+大数运算

#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

//#pragma comment(linker, "/STACK:1024000000,1024000000")

#define FIN             freopen("input.txt","r",stdin)
#define FOUT            freopen("output.txt","w",stdout)
#define fst             first
#define snd             second
#define rep(i, f, t)    for(int i = (f); i <= (t); i++)

//typedef __int64 LL;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;

const ULL MOD = 1000000000; /// 1e9

int T;
ULL A, B;
ULL X[] = {618033988, 749894848, 204586834};
ULL Y[2], Z[4];

bool check(ULL x, ULL y) {
if(x > y) swap(x, y);
/// 转化为1e9进制数的模拟乘法,计算k*618033988749894848204586834,结果保存在Z[]中
ULL k = y - x, temp = 0;
Y[0] = k / MOD, Y[1] = k % MOD;
Z[3] = (temp = X[2] * Y[1] + temp) % MOD, temp /= MOD;
Z[2] = (temp = X[1] * Y[1] + X[2] * Y[0] + temp) % MOD, temp /= MOD;
Z[1] = (temp = X[0] * Y[1] + X[1] * Y[0] + temp) % MOD, temp /= MOD;
Z[0] = (temp = X[0] * Y[0] + temp) % MOD, temp /= MOD;
return x == temp * MOD + k + Z[0];
}

int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
scanf("%d", &T);
while(T --) {
cin >> A >> B;
puts(check(A, B) ? "B" : "A");
}
return 0;
}


补充一个Java代码:

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 < 100; 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();
int T;
Scanner input = new Scanner(System.in);
T = input.nextInt();
while ((T --) != 0) {

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("B");
else System.out.println("A");
}
return;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: