CF173A Rock-Paper-Scissors 題解
阿新 • • 發佈:2021-12-16
CF173A Rock-Paper-Scissors 題解
,所以我們考慮將一個週期裡面每局的情況都統計出來,如果能湊出 \(\operatorname{lcm}(a_1,a_2)\) 局出來,就計算有多少個 \(\operatorname{lcm}(a_1,a_2)\) 局,顯然有 \(\left\lfloor\dfrac{n}{\operatorname{lcm}(a_1,a_2)}\right\rfloor\) 個,直接拿兩個人在每 \(\operatorname{lcm}(a_1,a_2)\) 局裡面輸的次數乘上 \(\left\lfloor\dfrac{n}{\operatorname{lcm}(a_1,a_2)}\right\rfloor\) ,再加上他們剩下來的幾局中的輸的次數即可。
Content
有 \(2\) 個人在玩石頭剪刀布,已知他們的出手都有一定的規律,求 \(n\) 局之後兩個人各輸了幾局。
資料範圍:\(1\leqslant n\leqslant 2\times 10^9\),週期長度不超過 \(10^3\)。
Solution
一個一個模擬肯定不現實,會 TLE,所以我們應當考慮是否有更快速的方法。
我們設第一個人的週期長度為 \(a_1\),第二個人的週期長度為 \(a_2\),則很容易發現,在 每 \(\operatorname{lcm}(a_1,a_2)\) 局裡面,他們輸的局數是固定的,因為他們正好能夠做完整數個週期,而且可以證明 \(\operatorname{lcm}(a_1,a_2)<10^6\)
Code
string s1, s2; int n, loses[1000007], loset[1000007], lose1, lose2, ans1, ans2; inline int gcd(int a, int b) {return !b ? a : gcd(b, a % b);} inline int lcm(int a, int b) {return a / gcd(a, b) * b;} //NOIP2020T1 血的教訓 int main() { n = Rint; str(s1, len1); str(s2, len2); int round = lcm(len1, len2); F(i, 0, round - 1) { if((s1[i % len1] == 'R' && s2[i % len2] == 'P') || (s1[i % len1] == 'P' && s2[i % len2] == 'S') || (s1[i % len1] == 'S' && s2[i % len2] == 'R')) loses[i + 1]++, lose1++; if((s2[i % len2] == 'R' && s1[i % len1] == 'P') || (s2[i % len2] == 'P' && s1[i % len1] == 'S') || (s2[i % len2] == 'S' && s1[i % len1] == 'R')) loset[i + 1]++, lose2++; } F(i, 1, n % round) ans1 += loses[i], ans2 += loset[i]; return printf("%d %d", ans1 + lose1 * (n / round), ans2 + lose2 * (n / round)), 0; }