Codeforces 897C Nephren gives a riddle(DFS)

Codeforces:Nephren gives a riddle

time limit per test: 2 seconds memory limit per test: 256 megabytes
input: standard input output: standard output

–What are you doing at the end of the world?
–Are you busy? Will you save us?

Codeforces 897C Nephren gives a riddle(DFS)_第1张图片
Nephren is playing a game with little leprechauns.

She gives them an infinite array of strings, f0… ∞.

f0 is “What are you doing at the end of the world? Are you busy? Will you save us?”.

She wants to let more people know about it, so she defines fi = What are you doing while sending “fi - 1”? Are you busy? Will you send “fi - 1”?” for all i ≥ 1.

For example, f1 is

"What are you doing while sending “What are you doing at the end of the world? Are you busy? Will you save us?”? Are you busy? Will you send “What are you doing at the end of the world? Are you busy? Will you save us?”?". Note that the quotes in the very beginning and in the very end are for clarity and are not a part of f1.

It can be seen that the characters in fi are letters, question marks, (possibly) quotation marks and spaces.

Nephren will ask the little leprechauns q times. Each time she will let them find the k-th character of fn. The characters are indexed starting from 1. If fn consists of less than k characters, output ‘.’ (without quotes).

Can you answer her queries?

Input

The first line contains one integer q (1 ≤ q ≤ 10) — the number of Nephren’s questions.

Each of the next q lines describes Nephren’s question and contains two integers n and k (0 ≤ n ≤ 105, 1 ≤ k ≤ 1018).

Output

One line containing q characters. The i-th character in it should be the answer for the i-th query.

Examples
Input
3
1 1
1 2
1 111111111111
Output
Wh.
Input
5
0 69
1 194
1 139
0 47
1 66
Output
abdef
Input
10
4 1825
3 75
3 530
4 1829
4 1651
3 187
4 584
4 255
4 774
2 474
Output
Areyoubusy
Note

For the first two examples, refer to f0 and f1 given in the legend.

·>原题

英语奇差的我一开始并没有明白题意。看懂之后也并没有能够在训练中做出来,训练结束后立刻修改了一点小错误就过了。

首先用本人很菜的英语水平对题目意思进行翻译:奈芙莲(Nephren) 给出了一个从 f0f 无限的字符串数组 ;

其中 f0 表示{What are you doing at the end of the world? Are you busy? Will you save us?}的字符串;(大括号内的部分表示字符串,不包括大括号)

而对于 fi 定义为 {What are you doing while sending “fi-1”? Are you busy? Will you send “fi-1”?}(i>=1)

比如 f1 表示为 {What are you doing while sending “f0”? Are you busy? Will you send “f0”?}

f1 = {What are you doing while sending “What are you doing at the end of the world? Are you busy? Will you save us?”? Are you busy? Will you send “What are you doing at the end of the world? Are you busy? Will you save us?”?} (其中黑体字表示 f0 )

fi 中的字符包括字母、问号、引号和空格。

奈芙莲将询问q次,每次都会要求找寻 n = i 个的 fn 的第 k 个字符。fn 开头由1数起,如果 fn 的字符数量少于 k ,则输出 “.” (没有引号);

输入
第一行为 q (1 ≤ q ≤ 10),表示有多少个提问;
接下来 q 行输入 n 和 k (0 ≤ n ≤ 105, 1 ≤ k ≤ 1018);

输出
一行包含 q 个字符的字符串,其中第 i 个字符对应第 i 个查询;

分析:

根据题目的 fi 的递推式,除了两部分 fi-1 的之外,还有三段字符串;分别是
前段 {What are you doing while sending “};
中段 {”? Are you busy? Will you send “};
后段 {”?};

如图所示结构

fi
前段
fi-1
中段
fi-1
后段
前段
fi-2
中段
fi-2
后段
前段
fi-2
中段
fi-2
后段

很容易会想到用DFS;
通过判断 k 落在五个部分的哪个部分,如果落在 fi-1 则递归判断,如果是在其他三个部分则返回对应的字符。如果 k 超出了范围则返回 “.”;

在递归时要稍微处理一下数据。判断落在什么区间需要用到对应的 fn 的长度,因为 fn 实在是太大了,n不到100而字符串长度就已经远远超过了long long表示的64位整型的范围(n<=10000),注意到k<=1018,那超过这个长度的 fn 及其以后的 fn 可以用一个设定的无穷大(如4e18,大于k)来处理判断 k 落在对应什么部分;

即预先保存四段字符后,得到各字符串的长度后进行各 fn 长度的预处理,实际上 q 只有10组的规模下是否预处理估计差别不大;

虽然能跑,但代码写得太难看了,有很多很糟糕的地方;
仍需要继续努力。

AC代码:

#include
#include
#include
#include
#include
#define MS(X) memset(X,0,sizeof(X))
typedef long long LL;
const LL INF=4e18;
using namespace std;
char f0[]={"What are you doing at the end of the world? Are you busy? Will you save us?"};
char ff[]={"What are you doing while sending \""};
char fm[]={"\"? Are you busy? Will you send \""};
char fb[]={"\"?"};
LL n,k,flen[100005],sn[11],sk[11];
int l0,lf,lm,lb,q;
void pre(){
    flen[0]=l0;
    for(int i=1;i<100005;i++){
        if(flen[i-1]>1e18) flen[i]=INF;
        else
            flen[i]=lf+2*flen[i-1]+lm+lb;
    }
}

char dfs(LL a,LL ft){		//这里我用ft来保存当前区间前面有多长的字符
    LL p=k-ft;							
    if(a==0) return p<=l0?f0[p-1]:'.';	//需要判断n为0时k的情况
    if(p<=lf) return ff[p-1];				//前段
    else if(lf<p && p<=lf+flen[a-1]) 			//fi-1
        return dfs(a-1,ft+lf);
    else if(lf+flen[a-1]<p && p<=lf+flen[a-1]+lm) //中段
        return fm[p-flen[a-1]-lf-1];
    else if(lf+flen[a-1]+lm<p && p<=lf+2*flen[a-1]+lm) 	//fi-1
        return dfs(a-1,ft+lf+flen[a-1]+lm);
    else if(lf+2*flen[a-1]+lm<p && p<=lf+2*flen[a-1]+lm+lb) //后段
        return fb[p-lf-2*flen[a-1]-lm-1];
    else return '.';					//此处判断不包括n为0
}

int main(){
    l0=strlen(f0);
    lf=strlen(ff);
    lm=strlen(fm);
    lb=strlen(fb);
    pre();
    scanf("%d",&q);
    for(int i=0;i<q;i++){
        scanf("%d%I64d",&sn[i],&sk[i]);
    }
    for(int i=0;i<q;i++){
        n=sn[i],k=sk[i];
        printf("%c",dfs(n,0));
    }
    puts("");
    return 0;
}

你可能感兴趣的:(train)