Advertisement
erek1e

CEOI '20 - Chess Rush (51pts)

Jul 13th, 2023
727
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.22 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. #define NDEBUG
  3.  
  4. using namespace std;
  5.  
  6. const int INF = 1e8;
  7. const int BASE = 1e9 + 7;
  8. inline int add(int x, int y) {
  9.     x += y;
  10.     if (x >= BASE) return x-BASE;
  11.     return x;
  12. }
  13.  
  14. int R, C;
  15. inline bool sameDiagonal(int x1, int y1, int x2, int y2) {
  16.     return x1-y1 == x2-y2 || x1+y1 == x2+y2;
  17. }
  18. inline bool sameColor(int x1, int y1, int x2, int y2) {
  19.     return ((x1+y1)-(x2+y2)) % 2 == 0;
  20. }
  21. inline bool inBoard(int r, int c) {
  22.     return r >= 1 && c >= 1 && r <= R && c <= C;
  23. }
  24. inline pair<int, int> diagonalIntersect(int x1, int y1, int x2, int y2) {
  25.     // x + y = x1 + y1
  26.     // x - y = x2 - y2
  27.     // x = (x1 + y1 + x2 - y2) / 2
  28.     // y = (x1 + y1 - x2 + y2) / 2
  29.     return {(x1+y1+x2-y2)/2, (x1+y1-x2+y2)/2};
  30. }
  31.  
  32. inline pair<int, int> downRight(int r, int c) {
  33.     return {r+C-c, C};
  34. }
  35. inline pair<int, int> downLeft(int r, int c) {
  36.     return {r+c-1, 1};
  37. }
  38.  
  39. inline pair<int, int> combine(pair<int, int> a, pair<int, int> b) { // (moves, ways)
  40.     if (a.first == b.first) return {a.first, add(a.second, b.second)};
  41.     else if (a.first < b.first) return a;
  42.     else return b;
  43. }
  44.  
  45. // going right
  46. inline pair<int, int> solveBishop(int c1, int cr) {
  47.     vector<int> ways(2*C), moves(2*C, INF);
  48.     ways[c1-1] = 1, moves[c1-1] = 1;
  49.     for (int r = 2; r <= R; ++r) {
  50.         vector<int> ways2(2*C), moves2(2*C, INF);
  51.  
  52.         auto can = [&](int pos, int dir, int w, int m) {
  53.             if (0 <= pos && pos < C) {
  54.                 if (m < moves2[dir*C+pos]) moves2[dir*C+pos] = m, ways2[dir*C+pos] = w;
  55.                 else if (m == moves2[dir*C+pos]) ways2[dir*C+pos] = add(ways2[dir*C+pos], w);
  56.             }
  57.         };
  58.         for (int i = 0; i < 2*C; ++i) {
  59.             int c = i%C, dir = i/C;
  60.             if (dir == 0) { // going right
  61.                 can(c+1, 0, ways[i], moves[i]);
  62.                 can(c-1, 1, ways[i], moves[i]+1);
  63.             } else { // going left
  64.                 can(c+1, 0, ways[i], moves[i]+1);
  65.                 can(c-1, 1, ways[i], moves[i]);
  66.             }
  67.         }
  68.         ways = ways2, moves = moves2;
  69.     }
  70.     return combine({moves[cr-1], ways[cr-1]}, {moves[cr-1+C], ways[cr-1+C]});
  71. }
  72.  
  73. inline int mult(int x, int y) {
  74.     return (long long)x*y % BASE;
  75. }
  76. struct Matrix {
  77.     int n, m;
  78.     vector<vector<int>> v;
  79.     Matrix() {}
  80.     Matrix(int N, int M): n(N), m(M) {
  81.         v.assign(n, vector<int>(m));
  82.     }
  83.     inline Matrix operator * (const Matrix &m2) const {
  84.         assert(m == m2.n);
  85.         int k = m2.m;
  86.         Matrix m3(n, k);
  87.         for (int i = 0; i < n; ++i) {
  88.             for (int j = 0; j < k; ++j) {
  89.                 for (int l = 0; l < m; ++l) {
  90.                     m3.v[i][j] = add(m3.v[i][j], mult(v[i][l], m2.v[l][j]));
  91.                 }
  92.             }
  93.         }
  94.         return m3;
  95.     }
  96.     inline Matrix bin_pow(int y) {
  97.         assert(n == m);
  98.         Matrix res(n, n);
  99.         for (int i = 0; i < n; ++i) res.v[i][i] = 1;
  100.         Matrix x = *this;
  101.         while (y) {
  102.             if (y & 1) res = res * x;
  103.             y >>= 1;
  104.             x = x * x;
  105.         }
  106.         return res;
  107.     }
  108. };
  109.  
  110. Matrix kingSquareMatrix;
  111. bool calculatedKingSquareMatrix = false;
  112. inline pair<int, int> solveKing(int c1, int cr) {
  113.     if (!calculatedKingSquareMatrix) {
  114.         Matrix multiplier(C, C);
  115.         for (int i = 0; i < C; ++i) {
  116.             for (int j = i-1; j <= i+1; ++j) {
  117.                 if (0 <= j && j < C) multiplier.v[j][i] = 1;
  118.             }
  119.         }
  120.         kingSquareMatrix = multiplier.bin_pow(R-1);
  121.         calculatedKingSquareMatrix = true;
  122.     }
  123.     return {R-1, kingSquareMatrix.v[cr-1][c1-1]};
  124. }
  125.  
  126. int main() {
  127.     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  128.     int Q; cin >> R >> C >> Q;
  129.     while (Q--) {
  130.         char t; int c1, cr;
  131.         cin >> t >> c1 >> cr;
  132.         if (t == 'P') {
  133.             if (c1 == cr) cout << R-1 << " 1\n";
  134.             else cout << "0 0\n";
  135.         } else if (t == 'R') {
  136.             if (c1 == cr) cout << "1 1\n";
  137.             else cout << "2 2\n";
  138.         } else if (t == 'Q') {
  139.             if (c1 == cr || sameDiagonal(1, c1, R, cr)) cout << "1 1\n";
  140.             else { // 2 moves
  141.                 int ways = 2 + 2; // Rook Rook, vertical Rook and Bishop (or vice versa)
  142.                 if (R == C && (c1 == 1 || c1 == C)) ++ways; // bishop + horizontal rook move
  143.                 if (R == C && (cr == 1 || cr == C)) ++ways; // horizontal rook move + bishop
  144.                 // both bishop moves:
  145.                 if (sameColor(1, c1, R, cr)) {
  146.                     auto [x1, y1] = diagonalIntersect(1, c1, R, cr);
  147.                     if (inBoard(x1, y1)) ++ways;
  148.                     auto [x2, y2] = diagonalIntersect(R, cr, 1, c1);
  149.                     if (inBoard(x2, y2)) ++ways;
  150.                 }
  151.                 cout << "2 " << ways << '\n';
  152.             }
  153.         } else if (t == 'B') {
  154.             pair<int, int> a = solveBishop(c1, cr), b = solveBishop(C+1-c1, C+1-cr);
  155.             auto [m, w] = combine(a, b);
  156.             if (m == INF) cout << "0 0\n";
  157.             else cout << m << ' ' << w << '\n';
  158.         } else { // t == 'K'
  159.             auto [m, w] = solveKing(c1, cr);
  160.             cout << m << ' ' << w << '\n';
  161.         }
  162.     }
  163.     return 0;
  164. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement