Secret Origins(数论,思维)

注意:这一篇用的不是位运算,偏规律和数学

思路:将测试样例全部转换成二进制来找规律,可知从头到尾找到第一个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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值