题目:达芬奇密码,高中时看的小说,都记不清那是几年前的事情了。(⊙_⊙)
已知一个字符串和这个字符串中每个大写字母对应的fib数,按照fib数列中数字的位置重新排列字符串。
分析:字符串处理、模拟题。
首先、打表计算Fib数列的前45个数(第46个超出2^31);
然后、对于每个读入的数字利用二分求出它在Fib中的位置;
最后、将输入串中的大写字母,按照上面求出的顺序排列,没有字母的位置的就是空格。
说明:1.只有大写字母才有和数字的对应关系,串里面可能有出大写字母外的其他字符,直接忽略;
2.数据格式比较恶心,建议一个一个字符的读入然后判断处理;
3.二分开始死循环,看了很久才发现把l写成了1(⊙_⊙)。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
int Fib[55],In[100];
int space( int data )
{
int l = 1,r = 45,mid;
while ( l < r ) {
mid = (l+r)/2;
if ( data > Fib[mid] )
l = mid+1;
else r = mid;
}
return r;
}
int main()
{
//dp计算Fib的前45个值,第46个超出2^31
Fib[1] = 1;Fib[2] = 2;
for ( int i = 3 ; i <= 45 ; ++ i )
Fib[i] = Fib[i-1] + Fib[i-2];
int T,N;
while ( scanf("%d",&T) != EOF )
while ( T -- ) {
scanf("%d",&N);
for ( int i = 0 ; i < N ; ++ i )
scanf("%d",&In[i]);
/* 数据读入 */
char buf[256],out[256];
memset( buf, 0, sizeof(buf) );
memset( out, 0, sizeof(out) );
int count = 0;
/* 过滤空格和回车 */
while ( buf[count] = getchar() )
if ( buf[count] == '\n' )
break;
/* 读取数据,值储存大写字母 */
while ( buf[count] = getchar() ) {
if ( buf[count] == '\n' )
break;
if ( buf[count] >= 'A' && buf[count] <= 'Z' )
count ++;
}
buf[count] = 0;
/* 将大写字母储存到Fib数编号对应的位置 */
int move = 0,save = 0,end = 0;
for ( int i = 0 ; i < N ; ++ i ) {
save = space(In[i])-1;
if ( save > end )
end = save;
out[save] = buf[move ++];
if ( move >= count )
break;
}
/* 输出 */
for ( int i = 0 ; i <= end ; ++ i )
if ( out[i] >= 'A' && out[i] <= 'Z' )
printf("%c",out[i]);
else printf(" ");
printf("\n");
}
return 0;
}