洛谷p3612:
思路:注意到n<=10^18,显然无法正常模拟,从前往后推无法实现。考虑从后往前推,将n的位置不断改变,当n<=字符串长度即可输出。n的改变方法:观察发现字符串先复制最后一个字符在从第一位复制到倒数第二位,假设n在长度为L字符串中,将该字符串从中间切割,判断n是否等于L/2+1,若是,则n=L/2,否则n=n-L/2-1,舍弃当前字符串后半部分,即回退到上次旋转,当n<=原始字符串长度即可输出。
实现代码:
循环:
# include <bits/stdc++.h>
using namespace std;
int main ()
{
string s;
cin>>s;
long long n;
cin>>n;
int x=s.size();//初始字符串长度
while(n>x)
{
long long len=x;//保存长度,防止影响x
while(n>len)len*=2;//找出当前n处于多大长度的字符串中
len/=2;
if(n==len+1)n-=1;
else n-=(len+1);//改变n的位置,舍弃当前字符串后半部分,即回退到上次旋转
}
cout<<s[n-1];//默认第一个字符为第1位,但是输入时第0位,所以-1;
return 0;
}
递归:思路一样就不解释了,原问题分解为不断寻找n位置的子问题
# include <bits/stdc++.h>
using namespace std;
string s;
long long n;
char found(long long n)
{
long long x=s.size();
long long len=x;
if(n<=x)return s[n-1];
while(n>len)len*=2;
len/=2;
if(n==len+1)found(len);
else found(n-len-1);
}
int main ()
{
cin>>s>>n;
cout<<found(n);
return 0;
}