Nephren gives a riddle
题意:给你一个初始串f[0]:"What are you doing at the end of the world? Are you busy? Will you save us?"(不包括引号)。为了让这句话被更多人知道定义串f[i]为"What are you doing while sending "fi - 1"? Are you busy? Will you send "fi - 1"?"(不包括第一个与最后一个引号),接下来有q次询问,每次询问第n个串的第k个字符是什么,这个字符可能是字母(大小写都有可能)、空格、问号或引号(因为每次引用前一个串的时候都会加上一个引号)。
思路:用一个数组来存放每个串的长度,而长度很好获得,从对串f[i]的定义中可以很容易的得到:从第一个串开始,每个串可以分为五个部分,其中:
第二、第四个串为f[i-1];
第一个串为:What are you doing while sending "(对没错,包括引号,这样才能保证第二、第四个串为f[i-1]);
第三个串为:"? Are you busy? Will you send ";
第五个串为:"?
其中第一、三、五个串的长度可以得到分别是:34、32、2,而第二、第四个串可以调用f[i-1]。
比赛的时候以为询问时k最大1e18就能用long long直接存下,wa的莫名其妙,赛后看了别人代码的 n >= 54 恍然大悟:当n为53时,串的长度已经达到1.2*1e18,所以53之后的串的前1e18个字符和第53个串的差别只有最前面的第一个串,所以对n和k同时处理即可。
AC代码:
/***********************************************
Author: StupidTurtle
Date: 2017.12.05
Email: 31601359@std.zucc.edu.cn
***********************************************/
#include <iostream>
#include <cstring>
#include <string>
using namespace std ;
typedef long long ll ;
ll q , n , k ;
string Head , Mid , End , F0 ;
ll l[100005] ;
void solve ( ll n , ll k ){
if ( n != 0 ){
if ( k <= 34 ){
cout << Head[k-1] ;
return ;
} else if ( k <= 34 + l[n-1] ){
solve ( n-1 , k-34 ) ;
} else if ( k <= 66 + l[n-1] ){
cout << Mid[k-34-l[n-1]-1] ;
return ;
} else if ( k <= 66 + l[n-1] * 2 ){
solve ( n-1 , k-66-l[n-1] );
} else {
cout << End[k-66-l[n-1]*2-1] ;
return ;
}
} else {
cout << F0[k-1] ;
}
}
int main(void){
Head = "What are you doing while sending \"" ;
// cout << Head.length() << endl ;
Mid = "\"? Are you busy? Will you send \"" ;
// cout << Mid.length() << endl ;
End = "\"?" ;
// cout << End.length() << endl ;
F0 = "What are you doing at the end of the world? Are you busy? Will you save us?" ;
// cout << F0.length() << endl ;
l[0] = 75 ;
for ( int i = 1 ; i <= 100000 ; i ++ ){
if ( i >= 54 ) l[i] = l[i-1];
else l[i] = l[i-1] * 2 + 68 ;
}
cin >> q ;
for ( int i = 0 ; i < q ; i ++ ){
cin >> n >> k ;
while ( n > 53 && k > 34 ){
n -- ;
k -= 34 ;
}
if ( k > l[n] ) cout << '.' ;
else solve ( n , k );
}
cout << endl ;
return 0;
}