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同时处理即可。
扫描二维码关注公众号,回复:
1071042 查看本文章
AC代码:
/*********************************************** Author: StupidTurtle Date: 2017.12.05 Email: [email protected] ***********************************************/ #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; }