Universal Solution
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Progressive nudges
Open only as much as you need to keep the solve alive.
Think about what happens at a single position of your string across all possible cyclic shifts of the opponent's string. What characters does position end up facing?
As the shift ranges from to , position of your string faces — which cycles through every character of exactly once. So every position faces the exact same multiset of opponent moves.
Since each position faces the same distribution of opponent moves (each character of appears exactly once across all shifts), the optimal choice at every position is the same: pick the move that beats the most characters in .
Count the occurrences of R, P, and S in the input. Playing R beats all the S's, playing P beats all the R's, and playing S beats all the P's. Pick whichever gives wins.
The answer string is just the same character repeated times (the one that beats the most frequent character), and the expected wins equal , which is always an integer — so the fraction is always .
Key Insight
Consider what a single position in your chosen string faces across all equally-likely cyclic shifts. When the shift is , position faces . As ranges over , the index takes every value in exactly once. So every position in your string faces the entire multiset of the opponent's characters, each exactly once.
Consequence
Since each position faces the same distribution, the optimal move at every position is the same: pick the RPS character that beats the largest group. Specifically:
- If has R's, P's, and S's, then:
- Playing P at a position beats all rocks across shifts
- Playing S at a position beats all papers across shifts
- Playing R at a position beats all scissors across shifts
The best choice beats opponents per position.
Expected Value
The expected number of wins is:
This is always an integer, so the output fraction is simply . The optimal string is just the winning character repeated times.
Complexity
per test case to count characters — about as chill as it gets.
Trap Alert
The problem asks for a fraction in lowest terms. Since is always a non-negative integer, the answer is always . Don't overthink the fraction part.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO(const string& name = "") {
ios::sync_with_stdio(false);
cin.tie(nullptr);
#ifdef ZK_LOCAL_RUN
freopen("f.in", "r", stdin);
freopen("f.out", "w", stdout);
#else
if (!name.empty()) {
freopen((name + ".in").c_str(), "r", stdin);
freopen((name + ".out").c_str(), "w", stdout);
}
#endif
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
string s;
cin >> s;
int n = s.size();
int r = 0, p = 0, sc = 0;
for (char c : s) {
if (c == 'R') r++;
else if (c == 'P') p++;
else sc++;
}
// P beats R, S beats P, R beats S
int mx = max({r, p, sc});
char best;
if (mx == r) best = 'P';
else if (mx == p) best = 'S';
else best = 'R';
cout << string(n, best) << "\n";
cout << mx << "/1\n";
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO(const string& name = "") {
ios::sync_with_stdio(false);
cin.tie(nullptr);
#ifdef ZK_LOCAL_RUN
freopen("f.in", "r", stdin);
freopen("f.out", "w", stdout);
#else
if (!name.empty()) {
freopen((name + ".in").c_str(), "r", stdin);
freopen((name + ".out").c_str(), "w", stdout);
}
#endif
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
string s;
cin >> s;
int n = s.size();
int r = 0, p = 0, sc = 0;
for (char c : s) {
if (c == 'R') r++;
else if (c == 'P') p++;
else sc++;
}
// P beats R, S beats P, R beats S
int mx = max({r, p, sc});
char best;
if (mx == r) best = 'P';
else if (mx == p) best = 'S';
else best = 'R';
cout << string(n, best) << "\n";
cout << mx << "/1\n";
}
return 0;
}