题目描述
解题思路
由题可知,第 k(k>1) 个字符串的组成为 第(k - 1)个字符串 + ‘m’ + (k+2)个 ‘o’ + 第(k - 1)个字符串,不难想到可以用递归简化问题,可以由 n 的值找到目标字符处在前一字符串中或处在当前字符串中间部分(即"mooooooooo…那里"),由此有了两个分支,递归终止条件为 目标字符在当前字符串中间部分 或 目标字符在1-3中 。
要想确定目标字符在当前字符串的位置,就需要知道S(k)的长度,由题意知 S(k)的长度 = 2 * S(k - 1)的长度 + k + 3,据此,再借助matlab工具可以得出当k>=27时,S(k)的长度就超过了109,因此只要用matlab先算出k为1到26的S(k)的长度,如下图
clc,clear
m=26;
a(1)=10;
for i=2:m
a(i)=2*a(i-1)+i+3;
end
a
由于数据量不多,可以事先将上述数据存入数组中,之后利用该数组,我们就可以知道目标字符在当前字符串的位置,通过递归,也可以推出在上一字符串中的位置,由此便可以得到最终答案。
代码
#include <iostream>
using namespace std;
int a[28] = {3, 10, 25, 56, 119, 246, 501, 1012, 2035, 4082, 8177, 16368, 32751, 65518, 131053, 262124, 524267, 1048554, 2097129, 4194280, 8388583, 16777190, 33554405, 67108836, 134217699, 268435426, 536870881, int(1e9)};
char mo(int ind, int n){
if (n == 1) return 'm';
else if (n == 2 || n == 3) return 'o';
int temp = n - a[ind - 1], addmo = ind + 3;
if (temp <= 0) return mo(ind - 1, n);
else if (temp == 1) return 'm';
else if (temp <= addmo) return 'o';
else return mo(ind - 1, temp - addmo);
}
int main(){
int n, ind;
cin >> n;
for (ind = 0; a[ind] < n; ind++);
cout << mo(ind, n) << endl;
return 0;
}