题意:给出长度为128二进制数,把他转化成十六进制,并且选择一次转换(把连续的0转换程::的形式)问转换后的最短的16进制的数是多少,若都一样则输出字典序最小的
思路:把128为拆成八个数,每个数为16位,然后把8个数字转化成16进制,转化完之后求把哪写转化成::的形式,这里可以用sum[]来求他的贡献,找出其中最大的sum[i]记录他的下标,若有多个最大的就优先最中间的转化,如果只有头和尾可以转化,并且sum的值相同,则优先选择尾部的即可
#include <cstdio>
#include <algorithm>
#include <cstring>
#include<math.h>
#include <iostream>
using namespace std;
char a[1010];
int sum[1010];
int op[1010];
int main(int argc, char *argv[])
{
int ca=1,t;
scanf("%d",&t);
while(t--)
{
scanf("%s",a);
int num=0,cnt=0,i;
memset(op,0,sizeof(op));
for(i=127;i>=0;i--)
{
op[num]+=(pow(2,cnt)*(a[i]-'0'));
if(cnt==15)
{
cnt=0;
num++;
continue;
}
cnt++;
}
memset(sum,0,sizeof(sum));
reverse(op,op+8);
int pos=0;
for(i=7;i>=0;i--)
{
if(op[i]==0)
{
sum[i]=sum[i+1]+1;
}
if(sum[i]>sum[pos])
{
pos=i;
}
if(sum[i]==sum[pos]&&sum[pos]+pos-1==7&&i!=0)
{
pos=i;
}
}
printf("Case #%d: ",ca++);
for(i=0;i<8;i++)
{
if(i==pos&&sum[i]>=2)
{
if(i==0)
{
printf("::");
}
else
printf(":");
i+=(sum[i]-1);
continue;
}
printf("%x",op[i]);
if(i!=7)printf(":");
}
printf("\n");
}
return 0;
}