cf div2 #449 C.Nephren gives a riddle

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:		[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;
}


猜你喜欢

转载自blog.csdn.net/stupid_turtle/article/details/78721769