std::vector<int> handId(64, -1); std::vector<std::vector<int>> hand(10, std::vector<int>(3, 0));
int nxtId[10][3][3];
int nxt[100][3][3][3][3];
void solve(){ #pragma region pre
int tot = 0; for(int r = 0; r <= 3; ++r){ for(int s = 0; r + s <= 3; ++s){ int p = 3 - r - s; int code = r * 16 + s * 4 + p; handId[code] = tot++; hand[handId[code]] = {r, s, p}; } }
auto encode = [&](const std::vector<int>& H) -> int { return H[0] * 16 + H[1] * 4 + H[2]; };
memset(nxtId, -1, sizeof(nxtId));
for(int id = 0; id < 10; ++id){ for(int play = 0; play < 3; ++play){ if(!hand[id][play]) continue; for(int draw = 0; draw < 3; ++draw){ auto H = hand[id]; --H[play], ++H[draw]; nxtId[id][play][draw] = handId[encode(H)]; } } }
memset(nxt, -1, sizeof(nxt));
for(int state = 0; state < 100; ++state){ int aId = state / 10, bId = state % 10; for(int ap = 0; ap < 3; ++ap){ if(!hand[aId][ap]) continue; for(int bp = 0; bp < 3; ++bp){ if(!hand[bId][bp]) continue; for(int ad = 0; ad < 3; ++ad){ for(int bd = 0; bd < 3; ++bd){ int nA = nxtId[aId][ap][ad]; int nB = nxtId[bId][bp][bd]; nxt[state][ap][bp][ad][bd] = nA * 10 + nB; } } } } } #pragma endregion
auto score = [&](int a, int b) -> int { if(a == b) return 1; if(a == 0 and b == 1) return 3; if(a == 1 and b == 2) return 3; if(a == 2 and b == 0) return 3; return 0; };
using ld = long double; const ld eps = 1e-14L;
const int MAXT = 20000; std::vector<std::vector<ld>> rec; rec.reserve(MAXT); std::vector<ld> pre(100), cur(100); rec.push_back(pre);
int rounds = 0; ld L = 0, R = 0;
while(rounds < MAXT){ for(int state = 0; state < 100; ++state){ int aId = state / 10, bId = state % 10; ld bestA = -1e100L;
for(int ap = 0; ap < 3; ++ap){ if(!hand[aId][ap]) continue; ld bestB = 1e100L;
for(int bp = 0; bp < 3; ++bp){ if(!hand[bId][bp]) continue; ld sum = 0.0L;
for(int ad = 0; ad < 3; ++ad){ for(int bd = 0; bd < 3; ++bd){ int ns = nxt[state][ap][bp][ad][bd]; sum += pre[ns]; } }
ld val = score(ap, bp) + sum / 9.0L; bestB = std::min(bestB, val); }
bestA = std::max(bestA, bestB); } cur[state] = bestA; }
++rounds; rec.push_back(cur); ld low = 1e100L, high = -1e100L; for(int state = 0; state < 100; ++state){ ld delta = cur[state] - pre[state]; low = std::min(low, delta); high = std::max(high, delta); } L = low, R = high; pre.swap(cur); if(R - L <= eps) break; }
ld inc = (L + R) / 2.0L; int T = read();
auto card = [&](char c) -> int { switch(c){ case 'R': return 0; case 'S': return 1; case 'P': return 2; } return -1; };
auto encode_s = [&](const std::string& s) -> int { std::vector<int> H(3, 0); for(char c : s) ++H[card(c)]; return encode(H); };
while(T--){ int k = read(); std::string A, B; std::cin >> A >> B; int aId = handId[encode_s(A)], bId = handId[encode_s(B)]; if(k <= rounds){ printf("%.12Lf\n", rec[k][aId * 10 + bId]); } else{ printf("%.12Lf\n", rec[rounds][aId * 10 + bId] + inc * (k - rounds)); } } }
|