注意:这一篇用的不是位运算,偏规律和数学
思路:将测试样例全部转换成二进制来找规律,可知从头到尾找到第一个01就把它交换成10,然后01后面全部的1在最后面开始放,放完了再放0(01后面的0),让1乘以2的n次方尽量地小
特例一:
1111100,没有01,则是直接从第二个1到最后一个1全部放在最后面,然后原本第一个1的位置改成0,在这个0的前面再放一个1
特例二:
11111,没有0,直接把第一个1换成0,前面放一个1
特例三:
1000000,只有一个1,直接乘以2就完事
#include<stdio.h>
#include<string.h>
#include<math.h>
int change(int *a,int max)
{
int i,j,num=0,k=1;
for(i=0;i<=max;i++)
{
num+=k*a[i];
k*=2;
}
return num;
}
int x[1000];
int main()
{
int q,t;
scanf("%d",&q);
for(t=1;t<=q;t++)
{
int j,i=0,n,m=0,u,s,num=0;
scanf("%d",&s);
n=s;
while(s>0)//搞成二进制
{
x[i]=s%2;
if(x[i]==1)
{
num++;
}
s/=2;
i++;
}
int len=i-1;
printf("Case %d: ",t);
if(num==i)//特判:如果全部是1,在第二个位置插入一个0
{
x[len]=0;
x[len+1]=1;
printf("%d\n",change(x,len+1));
continue;
}
if(num==1)//只有一个1,如100000这种形式,直接乘以2
{
printf("%d\n",2*n);
continue;
}
int num1=0,num0=0;
for(i=0;i<=len-2;i++)//逆序遍历,数01之前0和1个数
{
if(x[i]==1)
{
num1++;
}
if(x[i]==0)
{
num0++;
}
if(x[i]==1&&x[i+1]==0)
{
int temp;
temp=x[i];
x[i]=x[i+1];
x[i+1]=temp;
num1--;m=1;break;
}
}//出来的i是01中1的位置
if(m==0)//没有01,如1100,1111100,直接第一个1后面的1全放后面然后中间多一个0
{
for(j=0;j<=num1;j++)
{
x[j]=1;
}
for(j=num1+1;j<=num1+num0+1;j++)
{
x[j]=0;
}
x[num1+num0+2]=1;
printf("%d\n",change(x,len+1));
continue;
}
for(j=i-1;j>=i-num0;j--)//有01,1全放后面,然后放0
{
x[j]=0;
}
for(j=i-num0-1;j>=0;j--)
{
x[j]=1;
}
printf("%d\n",change(x,len));
}
return 0;
}