当前位置: 代码迷 >> 综合 >> 洛谷 [P3612 [USACO17JAN]Secret Cow Code S] {递推} 奋斗的珂珂~
  详细解决方案

洛谷 [P3612 [USACO17JAN]Secret Cow Code S] {递推} 奋斗的珂珂~

热度:20   发布时间:2024-01-31 02:21:25.0

题目描述

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.

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

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

给定初始字符串和索引,请帮助奶牛计算无限字符串中位置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≤ 1 0 18 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≤ 1 0 18 10^ {18} .
第二行输入N。请注意,数据可能很大,放进一个标准的32位整数可能不够,所以你可能要使用一个64位的整数类型(例如,在C / C++ 中是 long long)。

输出格式
Please output the Nth 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 的翻译

解题思路

首先,题目大意就是扩展字符串,每一次字符串的长度变为原来的2倍,且每一次增长的部分首字母是原来字符串的最后一个字母,增长部分剩余的字母是原来字符串从第一位到倒数第二位的字母。

首先,需要找到第一次大于给出的N的处理次数。(使用位运算可以节省时间)。
在这里插入图片描述
由上图我们可以看到,如果在不进行题目要求处理的直接延长,那么第二次出现3时数组下标应该为7(下标从一开始)如果按照题目要求进行处理那么第二次出现3时数组对应下标应该是8。

由此可以看出我们求解的答案递推应该是当前对应求解的数组下标M-1-L/2(L代表当前达到大于M的处理之后的字符串长度)。

此题需要特判,也就是说如果按照上式处理之后的值是0,代表此时对应的就是上一次扩展后的最后一个字符。

注意

1、N是long long 类型。(代码中是变量m)
2、使用字符串数组可以节省时间,本题尽量不要使用string。
3、位运算<<=1代表二进制左移一位,相当于*2。>>=1代表二进制右移一位,相当于/2。

完整代码

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const int maxn=100;
char a[maxn];int main()
{char c;int num=0;while(scanf("%c",&c),c!=' ')//输入字符串,使用string会慢 {a[++num]=c;//这样开始处理数组的下标第一个就是1 }ll m;scanf("%lld",&m);while(m>num)//不断折回 {ll i=num;while(i<m) i<<=1;i>>=1;//这一步可以省去一点时间 m-=(i+1);//递推的关键关键之处 if(m==0) m=i;//如果是那个单独处理的,最后一个元素,那么就特别处理一下 }printf("%c",a[m]);return 0;
} 
  相关解决方案