(博弈论 高精度小数)51NOD 1185 威佐夫游戏 V2

有2堆石子。A B两个人轮流拿,A先拿。每次可以从一堆中取任意个或从2堆中取相同数量的石子,但不可不取。拿到最后1颗石子的人获胜。假设A B都非常聪明,拿石子的过程中不会出现失误。给出2堆石子的数量,问最后谁能赢得比赛。
例如:2堆石子分别为3颗和5颗。那么不论A怎样拿,B都有对应的方法拿到最后1颗。
 
Input
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000)
第2 - T + 1行:每行2个数分别是2堆石子的数量,中间用空格分隔。(1 <= N <= 10^18)
Output
共T行,如果A获胜输出A,如果B获胜输出B。
Input示例
3
3 5
3 4
1 9
Output示例
B
A
A
解:众所周知,计算机表示的小数是一定程度内精确的,如本题(sqrt(5.0) + 1) / 2,double只精确到第16位(double保证15到16位有效数字,不是15到16位小数),而本题精度要求却在16位之后,所以我们需要找到更高精度的黄金比例,并且改进计算方式因为直接使用double还是会丢失精度。
 1 #include<stdio.h>
 2 
 3 #define M (int)1e9
 4 
 5 long long tmp[3] = {618033988,749894848,204586834 }; //更精确的(sqrt(5.0) + 1) / 2的小数部分
 6 
 7 int main()
 8 {
 9     int t;
10     while (scanf_s("%d", &t) != EOF)
11     {
12         while (t--)
13         {
14             long long a, b, temp, num[2];
15             scanf_s("%lld%lld", &a, &b);
16             if (a < b)
17             {
18                 temp = a;
19                 a = b;
20                 b = temp;
21             }
22             a -= b;
23             num[0] = a / M;
24             num[1] = a % M;
25             temp = tmp[2] * num[1];
26             temp = num[1] * tmp[1] + num[0] * tmp[2] + temp / M;
27             temp = num[1] * tmp[0] + num[0] * tmp[1] + temp / M;
28             temp = num[0] * tmp[0] + temp / M;
29             a += temp;
30             if (a == b) printf("B\n");
31             else printf("A\n");
32         }
33     }
34     return 0;
35 }

 

posted @ 2018-10-28 17:56  Ekalos  阅读(142)  评论(0编辑  收藏  举报