题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6869
威佐夫博弈原本是每次操作任取某堆的任意个石头1,或是从两堆中分别取出相同数量的石头2
方程为:
1 / t + 1 / t + 1 = 1;
当操作2修改为取出石头数量之差不超过k,即本题含义时,方程可为:
1 / t + 1 / 1 + k + t = 1;
判定条件为: an = n * t;
bn = an + (k + 1) * n;
若属于数列元素——lose 其余点——win [本题中讨论先手情况]
本文借鉴CSDN某萌萌哒大佬:https://blog.csdn.net/qq_43814654/article/details/108086427
*转载请附链接 谢谢
1 #include<iostream>
2 #include<algorithm>
3 #include<cstring>
4 #include<string>
5 #include<cstdio>
6 #include<cmath>
7
8 #define ll long long
9
10 using namespace std;
11
12 bool check(ll a, ll b, ll k)// 1/x + 1/1+k+x = 1 | x = ?
13 {
14 long double K = k;
15 long double t = (1.0 - K + sqrt(K * K + 2 * K + 5.0)) / 2.0;
16 //直接用long double 代入运算 方程解的精度很致命
17
18 ll l = 0, r = 1e9, mid;
19 while(l <= r){
20 mid = (l + r) >> 1;
21 ll tmp = (k + 1 + t) * mid;
22 if(b > tmp){
23 l = mid + 1;
24 }else if(b < tmp){
25 r = mid - 1;
26 }else{
27 if(a + (k + 1) * mid == b){
28 return true;
29 }
30 break;
31 }
32 }
33 return false;
34 }
35
36 int main(){
37 int T;scanf("%d",&T);
38 while(T--){
39 ll a, b, k;
40 scanf("%lld%lld%lld",&a,&b,&k);
41 if(a > b) swap(a, b);
42 if(check(a, b, k)){//true-lose false-win
43 printf("0
");
44 }else{
45 printf("1
");
46 }
47 }
48
49 return 0;
50 }