【倍增】Rigged Games
题意
两队打比赛,大比分 2b − 1 赢,小比分 2a − 1 赢。
给定的长度为 n 的串,两队比赛的每个小分结果是这个串的循环重复。
问从该串的每个位置开始,最终谁会赢得整个比赛。
思路
倍增。
首先对于每个位置,计算出它 \(2a-1\) 局后的比分的比分终点的位置。
然后采用倍增,即假设我们要从 \(j\) 跳 \(2^i\) 步,可以先从 \(j\) 跳 \(2^{i-1}\) 步,然后从跳 \(2^{i-1}\) 的终点也就是 \(jump_{2^{i-1},j}\) 再跳 \(2^{i-1}\) 步,即 \(jump_{i,j} = jump_{i-1,jump_{i-1},j}\) 。
同理,从 \(j\) 跳 \(2^i\) 步的得分我们也要累计起来,但这个时候要统计两部分的 a 小局比分,即 \(j\sim j+2^{i-1}\) 和 \(j+2^{i-1}\sim j+2^i\) 的。
最终判断的时候每次从 \(2^{17}\) 往后跳到凑出 \(2b-1\) 的比分即可。(\(2^{17}>1e5\))
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, a, b; cin >> n >> a >> b; vector jump(18, vector<int>(n)); vector sum(18, vector<int>(n)); string s; cin >> s; int sc[2] {}, r = 0; for (int i = 0; i < n; i ++) { while (sc[1] < a && sc[0] < a) { sc[s[r] - '0']++; r = (r + 1) % n; } jump[0][i] = r; sum[0][i] = sc[1] > sc[0]; sc[s[i] - '0']--; } for (int i = 1; i < 18; i ++) { for (int j = 0; j < n; j ++) { jump[i][j] = jump[i - 1][jump[i - 1][j]]; sum[i][j] = sum[i - 1][j] + sum[i - 1][jump[i - 1][j]]; } } int pos, res, ans; for (int i = 0; i < n; i ++) { pos = i, res = 0, ans = 0; for (int j = 17; j >= 0; j --) { if (res + (1 << j) <= 2 * b - 1) { res += 1 << j; ans += sum[j][pos]; pos = jump[j][pos]; } } cout << (ans >= b); } return 0; }
本文作者:Ke_scholar
本文链接:https://www.cnblogs.com/Kescholar/p/18355646
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步