Silchen有一个第1代字符串"FZU",现在定义一个下一代生成如下
字符'F'可以生成字符串"FZU"
字符'Z'可以生成字符串"FZ"
字符'U'可以生成字符串"FU"
例如:
第1代是"FZU"
第2代是"FZUFZFU"
第3代是"FZUFZFUFZUFZFZUFU"
Silchen想知道第n代的第k个位置的字符是什么
Input
题目包含多组测试数据,每组测试数据第一行是T表示组数
接下来有T行
每行两个整数n, k,表示Silchen想知道第n代第k个位置的字符是什么
0<T<=10 0<n<=100 0<k<=1000000000且保证位置k一定有字符
Output
每组测试数据输出第n代第k个位置的字符
Sample Input
3
1 1
2 5
3 3
Sample Output
F
Z
字符'F'可以生成字符串"FZU"
字符'Z'可以生成字符串"FZ"
字符'U'可以生成字符串"FU"
例如:
第1代是"FZU"
第2代是"FZUFZFU"
第3代是"FZUFZFUFZUFZFZUFU"
Silchen想知道第n代的第k个位置的字符是什么
Input
题目包含多组测试数据,每组测试数据第一行是T表示组数
接下来有T行
每行两个整数n, k,表示Silchen想知道第n代第k个位置的字符是什么
0<T<=10 0<n<=100 0<k<=1000000000且保证位置k一定有字符
Output
每组测试数据输出第n代第k个位置的字符
Sample Input
3
1 1
2 5
3 3
Sample Output
F
Z
U
思路:和之前校赛的那个题目类似,但是由于在火车这个题目没有细看,原来是一道很水的递归题目。
直接枚举是不太现实的,会TLE,所以要巧妙的递归,由于是父代生子代,所以我们可以计算出每一代字符有多少个,然后通过长度来不断缩小字符的范围,最后确定结果,一个细节是当n=24时,字符数量已经为1e9了。
详情看代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e5 + 5;
int f[105], n, k;
char solve(int l, int r, int step, int flag)
{
if(step == n + 1)
{
if(flag == 1) return 'F'; //第一部分
if(flag == 2) return 'Z'; //第二部分
return 'U'; //第三部分
}
if(flag == 1)
{
int a = f[n-step], b = (r - l + 1 - f[n-step]) / 2;//a为确定第一部分的位置 b为确定第二部分的位置
if(k < l + a) return solve(l, a + l - 1, step + 1, 1); //属于第一部分的内容
else if(k < l + a + b) return solve(l + a, l + a + b - 1, step + 1, 2);//属于第二部分的内容
else return solve(l + a + b, r, step + 1, 3);//属于第三部分的内容
}
else
{
int a = f[n-step], b = r - l + 1 - f[n-step];
if(k < l + a) return solve(l, a + l - 1, step + 1, 1);
else return solve(a + l, r, step + 1, flag);
}
}
int main()
{
f[0] = 1; f[1] = 3;
for(int i = 2; i <= 24; i++) f[i] = 2 * f[i-1] + f[i-2];//计算每一层的字符数量
int T;
while(scanf("%d", &T) == 1){
while(T--){
scanf("%d%d", &n, &k);
if(n > 24) n = 24;
char ch = solve(1, f[n], 1, 1);
printf("%c\n", ch);
}
}
return 0;
}