AtCoder ABC380D - Strange Mirroring 简单分治

题目链接:https://atcoder.jp/contests/abc380/tasks/abc380_d

题目大意:

给定一个字符串 \(S\),该字符串由大写和小写英文字母组成。

我们对 \(S\) 执行 \(10^{100}\) 次以下操作:

  • 首先,通过将 \(S\) 中的大写字母转换为小写字母,将小写字母转换为大写字母,创建一个字符串 \(T\)
  • 然后,按照此顺序连接 \(S\)\(T\) 形成一个新的 \(S\)

接下来有 \(Q\) 次询问。第 \(i\) 次查询给你一个整数 \(K_i\),你需要回答出:

  • 在所有操作(即上述的对字符串 \(S\) 执行的 \(10^{100}\) 次操作)完成后,字符串 \(S\) 从前往后的第 \(K_i\) 个字符是啥?

解题思路:

定义一个变量 \(c\) 表示当前反转的次数 \(\text{ mod } 2\) 的结果。

\(n\)\(S\) 能够得到的最短的 \(\gt K_i\) 的字符串。

\(K_i \gt n/2\),则将问题缩小一半后,K_i -= n/2; c ^= 1

最后,根据 \(c\) 的值确定是否对字符串进行大小写转换。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;

char s[maxn];
int n, q;

int main() {
    scanf("%s%d", s+1, &q);
    n = strlen(s+1);
    while (q--) {
        int c = 0;
        long long m = n, k;
        scanf("%lld", &k);
        while (m < k) m <<= 1;
        while (m != n) {
            if (k > m/2) {
                k -= m/2;
                c ^= 1;
            }
            m >>= 1;
        }
        if (!c) printf("%c ", s[k]);
        else printf("%c ", islower(s[k]) ? toupper(s[k]) : tolower(s[k]));
    }
    return 0;
}
posted @ 2024-12-31 12:20  quanjun  阅读(13)  评论(0)    收藏  举报