题目大意:
就是现在有一个皇后在棋盘的左上角, 棋盘大小n*m, n , m<= 1e12 (就是被这个大范围卡了精度....)
然后两个人轮流移动皇后, 每次可以向下, 右或者右下斜线方向移动, 移动步数至少一步, 至多不超出棋盘边界..然后谁将这个皇后移动到了右下角谁就输了
大致思路:
首先如果是到右下角赢的话就是威佐夫博奕的原形了
这个地方谁到右下角谁输, 我们不妨记右下角是(0, 0)
于是起点是(m - 1, n - 1), 我们画出P点和N点的示意图(必胜必败点示意图)如下:
可以你除了(1, 0), (0, 1), (2, 2)这3个P点的位置不同于威佐夫博弈之外, 其他的P点都是满足威佐夫博弈的性质的
那么对于这3个P点位置以及这3个位置能到达的点都特判一下, 然后对于其他的位置就是和威佐夫博弈一样的了
但是这题我用黄金分割比例的那个结论的时候, 写C++一直精度不够, long double也不行...于是最后换了Java重新写了一遍才过...
当然也有人不是用这个方法做的, 和斐波那契数列有关的方法...蒟蒻表示看不懂....
Java和C++的代码都附在下面了, 两者的逻辑是一样的...
不懂威佐夫博奕的可以看这里, 以及这里
代码如下:
Result : Accepted Memory : 0 KB Time : 560 ms
/* * Author Gatevin * Created Time : 2015/8/4 15:00:05 * File Name: Main.java */ import java.util.Scanner; import java.io.PrintWriter; import java.math.BigInteger; import java.util.Map; import java.util.HashMap; import java.util.Queue; import java.util.LinkedList; import java.io.FileOutputStream; import java.math.BigDecimal; public class Main{ public static String getGoldNumber(int n){ BigDecimal a = new BigDecimal(0.618); BigDecimal b = new BigDecimal("1"); for (int i = 1; i < n+1; i++) { a = b.divide(a.add(b), n, BigDecimal.ROUND_HALF_UP); } return a.toString(); } public static boolean check(long x, long y) { if(x > y) { Long t = x; x = y; y = t; } if(x == 0 && y == 1) return true; if(x == 0 && y != 1) return false; if(x == 2 && y == 2) return true; if(x == 2 && y != 2) return false; if(x == 1) return false; BigDecimal X = new BigDecimal(x); long k = gold2.multiply(X).longValue(); BigDecimal K = new BigDecimal(k); if(gold.multiply(K.add(one)).longValue() == x) k++; K = new BigDecimal(k); long tx = gold.multiply(K).longValue(); if(tx == x && y == x + k) return true; return false; } static String goldString = getGoldNumber(200);//精确到200位 static BigDecimal gold2 = new BigDecimal(goldString); static BigDecimal one = new BigDecimal(1); static BigDecimal gold = gold2.add(one); public static void main(String args[]){ /* //267914296 433494437 BigDecimal n = new BigDecimal(267914295); BigDecimal m = new BigDecimal(433494436); m = m.subtract(n); m = m.multiply(g); System.out.println(m); */ int T; Scanner cin = new Scanner(System.in); T = cin.nextInt(); long n, m; for(int cas = 1; cas <= T; cas++) { n = cin.nextLong(); m = cin.nextLong(); long x = m - 1; long y = n - 1; if(check(x, y)) { System.out.println(2); continue; } if(x <= 2 || y <= 2) { if(x == 1 && y == 1) System.out.println("1 1 0"); else if(x == 1 && y == 2) System.out.println("1 2 0"); else if(x == 2 && y == 1) System.out.println("1 0 2"); else { if(x == 1) System.out.printf("1 %d 0\n", y); else if(y == 1) System.out.printf("1 0 %d\n", x); else if(x == 2) System.out.printf("1 %d 0\n", y - 2); else if(y == 2) System.out.printf("1 0 %d\n", x - 2); } continue; } if(x == y) { System.out.printf("1 %d %d\n",x - 2, y - 2); continue; } if(Math.abs(x - y) == 1) { if(x > y) System.out.printf("1 %d %d\n", y, y); else System.out.printf("1 %d %d\n", x, x); continue; } if(Math.abs(x - y) >= 2) { BigDecimal xy = new BigDecimal(Math.abs(x - y)); long t = gold.multiply(xy).longValue(); if(x < y && t < x) { System.out.printf("1 %d %d\n", x - t, x - t); continue; } if(y < x && t < y) { System.out.printf("1 %d %d\n", y - t, y - t); continue; } } BigDecimal X = new BigDecimal(x); BigDecimal Y = new BigDecimal(y); long k = gold2.multiply(X).longValue(); BigDecimal K = new BigDecimal(k); if(gold.multiply(K.add(one)).longValue() == x) k++; K = new BigDecimal(k); long tx = gold.multiply(K).longValue(); if(k >= 2 && tx == x) if(y > x + k) { System.out.printf("1 %d 0\n", y - (x + k)); continue; } k = gold2.multiply(gold2.multiply(X)).longValue(); K = new BigDecimal(k); if(gold.multiply(gold.multiply(K.add(one))).longValue() == x) k++; K = new BigDecimal(k); tx = gold.multiply(gold.multiply(K)).longValue(); if(k >= 2 && tx == x) if(y > x - k) { System.out.printf("1 %d 0\n", y - (x - k)); continue; } k = gold2.multiply(Y).longValue(); K = new BigDecimal(k); if(gold.multiply(K.add(one)).longValue() == y) k++; K = new BigDecimal(k); long ty = gold.multiply(K).longValue(); if(k >= 2 && ty == y) if(x > y + k) { System.out.printf("1 0 %d\n", x - (y + k)); continue; } k = gold2.multiply(gold2.multiply(Y)).longValue(); K = new BigDecimal(k); if(gold.multiply(gold.multiply(K.add(one))).longValue() == y) k++; K = new BigDecimal(k); ty = gold.multiply(gold.multiply(K)).longValue(); if(k >= 2 && ty == y) if(x > y - k) { System.out.printf("1 0 %d\n", x - (y - k)); continue; } System.out.println("What the fuck!"); } } }
Result : Wrong Answer on test 11
/* * Author: Gatevin * Created Time: 2015/8/14 15:12:26 * File Name: Sakura_Chiyo.cpp */ #include<iostream> #include<sstream> #include<fstream> #include<vector> #include<list> #include<deque> #include<queue> #include<stack> #include<map> #include<set> #include<bitset> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<cmath> #include<ctime> #include<iomanip> using namespace std; const double eps(1e-8); typedef long long lint; const double gold = (1 + sqrt(5.)) / 2; const double gold2 = (sqrt(5.) - 1) / 2; bool check(lint x, lint y) { if(x > y) swap(x, y); if(x == 0 && y == 1) return 1; if(x == 0 && y != 1) return 0; if(x == 2 && y == 2) return 1; if(x == 2 && y != 2) return 0; if(x == 1) return 0; lint k = floor(x*gold2); if((lint)floor((k + 1)*gold) == x) k++; if((lint)floor(k*gold) == x && y == x + k) return 1; return 0; } int main() { int T; //double xx = 1000000000001.999; //printf("%I64d\n",(long long)floor(xx)); //printf("%I64d\n", (long long)xx); //freopen("A.cpp", "r", stdin); //freopen("out.out", "w", stdout); scanf("%d", &T); lint n, m; while(T--) { scanf("%I64d %I64d", &n, &m); lint x = m - 1, y = n - 1;//find a, b, such that (px - b, py - a) is P position if(check(x, y))//P ? { puts("2"); continue; } //printf("1"); //x, y, <= 2 tepan if(x <= 2 || y <= 2) { if(x == 1 && y == 1) printf("1 1 0\n"); else if(x == 1 && y == 2) printf("1 2 0\n"); else if(x == 2 && y == 1) printf("1 0 2\n"); else { if(x == 1) printf("1 %I64d 0\n", y); else if(y == 1) printf("1 0 %I64d\n", x); else if(x == 2) printf("1 %I64d 0\n", y - 2); else if(y == 2) printf("1 0 %I64d\n", x - 2); } continue; } if(x == y) { printf("1 %I64d %I64d\n", x - 2, y - 2); continue; } if(abs(x - y) == 1)//go to 1, 0 or 0, 1 { if(x > y)//1 0 { printf("1 %I64d %I64d\n", y, y); } else//0 1 printf("1 %I64d %I64d\n", x, x); continue; } //only remain go to gold point if(abs(x - y) >= 2)//take 2 piles { lint t = (lint)floor(abs(x - y)*gold); //cout<<"hehe"<<" "<<t<<" "<<abs(x - y)<<" "<<x<<" "<<y<<endl; if(x < y) { if(t < x) { printf("1 %I64d %I64d\n", x - t, x - t); continue; } } if(y < x) { if(t < y) { printf("1 %I64d %I64d\n", y - t, y - t); continue; } } } //else take one pile //take y pile //then x = A[i] or x = B[i] //cout<<"now"<<endl; //x = A[i] lint k = floor(x*gold2); if((lint)floor((k + 1)*gold) == x) k++; if(k >= 2 && (lint)floor(k*gold) == x) if(y > x + k) { printf("1 %I64d 0\n", y - (x + k)); continue; } //x = B[i] k = floor(x*gold2*gold2); if((lint)floor((k + 1)*gold*gold) == x) k++; if(k >= 2 && (lint)floor(k*gold*gold) == x) { if(y > x - k) { printf("1 %I64d 0\n", y - (x - k)); continue; } } //cout<<"hehe"<<endl; //take x pile //y = A[i]; //cout<<"hehehe"<<endl; k = floor(y*gold2); if((lint)floor((k + 1)*gold) == y) k++; if(k >= 2 && (lint)floor(k*gold) == y) if(x > y + k) { //cout<<0<<" "<<y + k<<" "<<x<<endl; printf("1 0 %I64d\n", x - (y + k)); continue; } //y = B[i] //cout<<"ppp"<<endl; k = floor(y*gold2*gold2); if((lint)floor((k + 1)*gold*gold) == y) k++; if(k >= 2 && (lint)floor(k*gold*gold) == y) { if(x > y - k) { printf("1 0 %I64d\n", x - (y - k)); continue; } } //cout<<"nani"<<endl; //puts("2"); // printf("What the fuck %I64d %I64d\n", n, m); // while( 1 ); } return 0; }