洛谷P3612(递归)
题目描述
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 ss, let F(s)F(s) be ss followed by ss "rotated" one character to the right (in a right rotation, the last character of ss rotates around and becomes the new first character). Given an initial string ss, the cows build their infinite-length code string by repeatedly applying FF; each step therefore doubles the length of the current string.
Given the initial string and an index NN, please help the cows compute the character at the NNth position within the infinite code string.
输入格式
The input consists of a single line containing a string followed by NN. The string consists of at most 30 uppercase characters, and N≤1018N≤1018.
Note that NN 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++).
输出格式
Please output the NNth character of the infinite code built from the initial string. The first character is N=1N=1.
题意翻译
奶牛正在试验秘密代码,并设计了一种方法来创建一个无限长的字符串作为其代码的一部分使用。
给定一个字符串,让后面的字符旋转一次(每一次正确的旋转,最后一个字符都会成为新的第一个字符)。也就是说,给定一个初始字符串,之后的每一步都会增加当前字符串的长度。
给定初始字符串和索引,请帮助奶牛计算无限字符串中位置 NN 的字符。
第一行输入一个字符串。该字符串包含最多 3030 个大写字母,数据保证 N≤1018N≤1018 。
第二行输入 NN。请注意,数据可能很大,放进一个标准的 3232 位整数可能不够,所以你可能要使用一个 6464 位的整数类型(例如,在 C/C++ 中是 long long
)。
请输出从初始字符串生成的无限字符串中的位置的字符。第一个字符是 N=1N=1.。
感谢@y_z_h 的翻译
输入输出样例
输入 #1复制
COW 8
输出 #1复制
C
说明/提示
In this example, the initial string COW expands as follows:
COW -> COWWCO -> COWWCOOCOWWC
12345678
首先分析数据范围n的范围是1e18 所以模拟题中的过程是不行会超时,然后我们知道这段字符串是如何复制而来的,所以可以采取倒推的方法,从当前n处的位置,推出n在进行复制之前的位置,n的位置共有两种情况,因为复制是先把最后的元素复制再把前面的元素复制下来。由此我们便可以通过递归的方式把n对应到题中所给的字符串的位置。
第一步:先确定n所在位置,按题中所给的方式得到的字符串的长度。
第二步:推位置对应的公式,我们不妨设n在复制之前的位置为k。当n 是第一个元素时,这时k+1 = n, k == l/2;当 n 不是最后一个元素时, 这时 k + l /2 + 1 = n;
第三步:递归,每次缩短一半的长度,然后每次更新 字符的位置,直到当前字符的位置在最初题中所给字符的长度之内。
#include <iostream>
using namespace std;
typedef long long LL;
LL n;
int main() {
string str = " ";
cin >> str >> n;
LL l = str.length();
LL num = l;
while(l < n) l *= 2;
l /= 2;
while(n > num ) {
if( n - l > 1) n -= (l + 1);
else if(n == l + 1) n = l;
l /= 2;
}
cout << str[n - 1];
return 0;
}