牛客寒假算法基础集训营1 B 炸鸡块君与FIFA22(倍增)
题目大意:
给出一个字符串表示每局游戏的结果,每次询问格式为 ,询问若你初始有 分,按从左到右的顺序经历了 这一子串的游戏结果后,最终分数是多少。
思路:
对于模 3 意义下相同的初始分数 ,经历了 这一段游戏结果后的变化量是相同的。
我们考虑使用倍增加速查询的过程。
设计状态 表示在初始分数为 的情况下,经历了这段游戏后的分数变化量。
每次转移时注意由相应的初始分数状态得到即可。
关于倍增怎样跳着去下一个状态:
对于一个区间 ,区间长度 len 是一个定值,对应一个唯一的二进制表示,每一位的 0/1 就表示我们对于 的选取情况,并且选取情况也是唯一的。
例如 8 的二进制表示为 1000,7 的二进制表示为 0111,如果不选择 ,那么后面就算全选也达不到 ,所以选取情况唯一。
Code:
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int n, q; cin >> n >> q;
string s; cin >> s;
s = " " + s;
auto mod3 = [&](int x) {
return (x % 3 + 3) % 3;
};
//go[k][i][j] 表示在初始分数为k的情况下,经历了[j, j + 2^i - 1]这段游戏后的分数变化量
vector<vector<vector<int>>> go(3, vector<vector<int>>(24 + 1, vector<int>(n + 1)));
for (int j = 1; j <= n; j++) {
if (s[j] == 'W')
for (int k = 0; k < 3; k++)
go[k][0][j] = 1;
else if (s[j] == 'L')
go[0][0][j] = 0, go[1][0][j] = -1, go[2][0][j] = -1;
}
for (int i = 1; i <= 24; i++) {
for (int j = 1; j <= n; j++) {
int m = j + (1 << (i - 1));
if (m <= n) // 没越界
for (int k = 0; k < 3; k++)
go[k][i][j] = go[k][i - 1][j] + go[mod3(k + go[k][i - 1][j])][i - 1][m];
}
}
while (q--) {
int l, r, s; cin >> l >> r >> s;
int now = l;
while (now <= r) {
int power = 0;
while (now + (1 << power) - 1 <= r) //跳多少
power++;
power--;
s += go[s % 3][power][now]; //根据分数模3结果访问对应值
now += (1 << power);
}
cout << s << "\n";
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】