Forever Young

洛谷 P3612 [USACO17JAN]Secret Cow Code S

思路

分治

设原串长度为 \(len\),要查询的位置为 \(pos\),考虑如何一步步分治令 \(pos\) 变为小于等于 \(len\) 的数 \(pos'\),且 \(s_{pos}=s_{pos'}\)

先定义一个 \(n\) 记录何时字符串的长度大于 \(pos\),然后根据题意,很容易得出如果某个字符 \(pos\) 在长度为 \(n\) 的字符串的后半段,那么第 \(pos-1-\frac n2\) 一定与第 \(pos\) 个字符相同。

但是当 \(n/2+1=pos\) 时,\(pos\) 的值应该等于 \(pos-1\),即 \(n/2\),所以这种情况要特判,由此写出以下代码

  while (n != len) {
    n = n / 2;
    if (pos <= n) continue;
    n + 1 == pos ? pos = n : pos -= 1 + n;
  }

代码

/*
  Name: P3612 [USACO17JAN]Secret Cow Code S
  Author: Loceaner
  Date: 31/08/20 15:41
  Description:
  Debug:
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;

const int A = 1e5 + 11;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

inline int read() {
  char c = getchar();
  int x = 0, f = 1;
  for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
  for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
  return x * f;
}

char s[1001];
int n, len, pos, cnt;

signed main() {
  scanf("%s", s + 1), pos = read();
  n = len = strlen(s + 1);
  while (n < pos) n *= 2;
  while (n != len) {
    n = n / 2;
    if (pos <= n) continue;
    n + 1 == pos ? pos = n : pos -= 1 + n;
  }
  cout << s[pos] << '\n';
  return 0;
}
posted @ 2020-08-31 17:41  Loceaner  阅读(216)  评论(0)    收藏  举报