[luogu p3612] [USACO17JAN]Secret Cow Code S

传送门

[USACO17JAN]Secret Cow Code S

题目描述

The cows are experimenting with secret codes, and have devised a method for creating an infinite-length string to be used as part of one of their codes.

Given a string \(s\), let \(F(s)\) be \(s\) followed by \(s\) "rotated" one character to the right (in a right rotation, the last character of \(s\) rotates around and becomes the new first character).

Given an initial string \(s\), the cows build their infinite-length code string by repeatedly applying \(F\); each step therefore doubles the length of the current string. Given the initial string and an index \(N\), please help the cows compute the character at the \(N\)th position within the infinite code string.

奶牛正在试验秘密代码,并设计了一种方法来创建一个无限长的字符串作为其代码的一部分使用。

给定一个字符串,让后面的字符旋转一次(每一次正确的旋转,最后一个字符都会成为新的第一个字符)。也就是说,给定一个初始字符串,之后的每一步都会增加当前字符串的长度。

给定初始字符串和索引,请帮助奶牛计算无限字符串中位置N的字符。

输入输出格式

输入格式

The input consists of a single line containing a string followed by \(N\). The string consists of at most 30 uppercase characters, and \(N \leq 10^{18}\).

Note that \(N\) may be too large to fit into a standard 32-bit integer, so you may want to use a 64-bit integer type (e.g., a "long long" in C/C++).

第一行输入一个字符串。该字符串包含最多30个大写字母,并 \(N \leq 10^{18}\)

第二行输入N。请注意,数据可能很大,放进一个标准的32位整数可能不够,所以你可能要使用一个64位的整数类型(例如,在C / C++ 中是 long long)。

输出格式

Please output the \(N\)th character of the infinite code built from the initial string. The first character is \(N=1\).

请输出从初始字符串生成的无限字符串中的位置的字符。第一个字符是 \(N=1\).。

输入输出样例

输入样例 #1

COW 8

输出样例 #1

C

说明

In this example, the initial string COW expands as follows:

COW -> COWWCO -> COWWCOOCOWWC

12345678

感谢@y_z_h 的翻译

分析

首先说明一下,此题中right rotation翻译有误,不应是“正确的旋转”,而是“向右旋转”。不过对题意影响不大。

首先观察样例:

COW -> CO W W CO -> COWWC O O COWWC

很明显对于总串,第一位到第二位的子串和第五位到第六位的子串是一样的,而再扩张,第一位到第五位的子串和第八位到第十二位的子串是一样的。

那么我们就可以不断的删除前面那一半的字符串,最后剩下原字符串直接输出就可以了。

当然实际实现我们不可能直接实现扩张这个字符串,因为\(n\)的范围很明显不能让我们这么做,所以实际上我们是把\(n\)通过这种方式不断的减下去,但又得保证减下去得到的索引\(n^\prime\)和原索引\(n\)对应的字符是一样的,直到\(n^\prime \le \operatorname{len}(s)\)\(s\)是原串)

如果还是不理解,建议画图。

代码

/*
 * @Author: crab-in-the-northeast 
 * @Date: 2020-04-26 09:50:00 
 * @Last Modified by: crab-in-the-northeast
 * @Last Modified time: 2020-04-26 10:20:37
 */
#include <iostream>
#include <cstdio>
#include <string>

std :: string s;
long long n;

int main() {
    std :: cin >> s >> n;
    s = ' ' + s;
    int len = s.length()  - 1;
    while(len < n) {
        long long mid = len;
        while(mid * 2 < n) mid <<= 1;
        n -= (mid + 1);
        if(n == 0) n = mid;
    }
    std :: cout << s[n] << std :: endl;
    return 0;
}

评测结果

AC 100:R33123488

posted @ 2020-04-26 10:22  dbxxx  阅读(374)  评论(0编辑  收藏  举报