P1010【NOIP1998普及组】幂次方

文章讲述了如何解决一个编程问题,将输入的十进制数转换为特定格式的二进制数,通过预处理和巧妙的编码策略简化了代码实现。文章详细介绍了两种方法:一种是使用数组存储和嵌套解法,另一种是递归和对数转换法,最后还提及了位运算符的解决方案。
摘要由CSDN通过智能技术生成

(此为洛谷题)

这题目一看,就感觉很麻烦,不仅要给输入的数转化为二进制,而且要把得出来的数也统统转化为二进制,但是数据最大就2*10^4

也就是说,他不超过2^15,只要用1到14就能表示转化过的数(指2的次方中的数)

说明实际上不要多次转换,只要提前把1到14转换成题目所需格式就可以:

//1     2(0)

//2     2

//3     2+2(0)

//4     2(2)

//5     2(2)+2(0)

//6     2(2)+2

//7     2(2)+2+2(0)

//8     2(2+2(0))

//9     2(2+2(0))+2(0)

//10    2(2+2(0))+2

//11    2(2+2(0))+2+2(0)

//12    2(2+2(0))+2(2)

//13    2(2+2(0))+2(2)+2(0)

//14    2(2+2(0))+2(2)+2

然后完成第一步(将输入的数转化为二进制),按需输出就可以了

代码实现:

#include<stdio.h>

int main(void)
{
    //提前处理
    int k[15] = {0};
    int n, i;
    int num = 0;//用来记1的数量并调节输出“+”
    scanf("%d", &n);

    //十进制转二进制
    for(i = 0; n != 1; i++)
    {
        if(k[i] = n % 2)
            num++;
        n /= 2;
    }
    k[i] = 1;

    //输出处理
    for(int j = i; j >= 0; j--)
    {
        switch(j)
        {
            case 0:
                if(k[j])
                    printf("2(0)");
                break;
            case 1:
                if(k[j])printf("2");
                break;
            case 2:
                if(k[j])
                    printf("2(2)");
                break;
            case 3:
                if(k[j])
                    printf("2(2+2(0))");
                break;
            case 4:
                if(k[j])
                    printf("2(2(2))");
                break;
            case 5:
                if(k[j])
                    printf("2(2(2)+2(0))");
                break;
            case 6:
                if(k[j])
                    printf("2(2(2)+2)");
                break;
            case 7:
                if(k[j])
                    printf("2(2(2)+2+2(0))");
                break;
            case 8:
                if(k[j])
                    printf("2(2(2+2(0)))");
                break;
            case 9:
                if(k[j])
                    printf("2(2(2+2(0))+2(0))");
                break;
            case 10:
                if(k[j])
                    printf("2(2(2+2(0))+2)");
                break;
            case 11:
                if(k[j])
                    printf("2(2(2+2(0))+2+2(0))");
                break;
            case 12:
                if(k[j])
                    printf("2(2(2+2(0))+2(2))");
            case 13:
                if(k[j])
                    printf("2(2(2+2(0))+2(2)+2(0))");
                break;
            case 14:
                if(k[j])
                    printf("2(2+2(0))+2(2)+2");
                break;
        }
        if(k[j] && num != 0)
        {
            printf("+");
            num--;
        }
    }
    
    return 0;
}
//1     2(0)
//2     2
//3     2+2(0)
//4     2(2)
//5     2(2)+2(0)
//6     2(2)+2
//7     2(2)+2+2(0)
//8     2(2+2(0))
//9     2(2+2(0))+2(0)
//10    2(2+2(0))+2
//11    2(2+2(0))+2+2(0)
//12    2(2+2(0))+2(2)
//13    2(2+2(0))+2(2)+2(0)
//14    2(2+2(0))+2(2)+2

实际上应该不断嵌套解的,这也是一种偷鸡的方法(乐)

不过洛谷的测试点5有问题呀

输入是16385

而测试输出是2(2(2+2(0))+2(2)+2)+2(0)

不管怎么说也应该是2(2(2+2(0))+2(2)+2+2(0)呀(就是把那个奇怪的括号去掉)

(补充:后面发现是自己在2^14处的输出有问题。。。偷鸡有风险啊。。。)

以后有机会试一试不偷鸡的方法

补充:

来了来了,第二天就试了一下不偷鸡的方法,发现还挺好写的(我之前累死累活把1~14手动转化为二进制是为了什么)(偷鸡的代价)

附上代码:

#include<stdio.h>
void Power_to_the_power(int n);

//主函数
int main(void)
{
    int num;
    scanf("%d", &num);
    Power_to_the_power(num);

    return 0;
}
//函数
void Power_to_the_power(int n)
{
    int k[15] = {0};
    int length = 0;
    int i;

    //十进制转二进制(因为获得的二进制是逆序的,所以还是需要存储)(输出是顺序的)
    for(i = 0; n != 1; i++)
    {
        if(k[i] = n % 2)
            length++;
        n /= 2;
    }
    k[i] = 1;

    //开始输出以及递归
    for(; i > -1; i--)
    {
        if(k[i])
        {
            switch (i)
            {
            case 0:
                printf("2(0)");
                break;
            case 1:
                printf("2");
                break;
            default:
                printf("2(");
                Power_to_the_power(i);
                printf(")");
                break;
            }
            if(length != 0)
            {
                printf("+");
                length--;
            }
        }
    }
    return;
}

但是还是有可以改进的地方,因为我用的是常规的十进制转二进制的方法,所得到的二进制数是从低到高的,只能设置数组存储,以后学一学把十进制顺序转二进制的方法,就可以一边计算一边输出了,不需要存储。

补充:

嗨嗨嗨,我又来了。

上网搜了搜将十进制转化为二进制的方法,发现清一色的整除取余法,没有一个是顺序输出的。后面自己就想到了对数转化法。

就是先用log来转化所需要的数(函数为log()或者log10(),具体上网搜),得到一个数,这个数取整数部分就是该数转化为二进制的最高位。

通过这个思路,就可以完成十进制向二进制的顺序转化了。

代码如下:

#include<stdio.h>
#include<math.h>
void Decimal_to_binary(int );

int main(void)
{
    int n;
    scanf("%d", &n);
    Decimal_to_binary(n);

    return 0;
}
void Decimal_to_binary(int n)
{
    int num = log(n) / log(2);
    while(n)
    {
        int new_num = log(n) / log(2);
        n -= pow(2, new_num);
        for(int j = 0; j < (num - new_num - 1); j++)
            printf("0");
        printf("1");
        num = new_num;
    }
    //考虑最低位为0的情况
    while(num--)
        printf("0");

    return;
}

通过这种方法,我们可以进一步优化题解:

#include<stdio.h>
#include<math.h>
void Decimal_to_binary(int );

int main(void)
{
    int n;
    scanf("%d", &n);
    Decimal_to_binary(n);

    return 0;
}
void Decimal_to_binary(int n)
{
    while(n)
    {
        int new_num = log(n) / log(2);
        n -= pow(2, new_num);
        if(new_num > 1)
        {
            printf("2(");
            Decimal_to_binary(new_num);
            printf(")");
        }
        else if(new_num)
            printf("2");
        else
            printf("2(0)");
        //考虑需要用+的情况
        if(n)
            printf("+");
    }

    return;
}

代码简洁多了,真不错

补充:还有一个用位运算符来进行十进制转化为二进制的

代码如下:

#include<stdio.h>
#include<limits.h>
char * itobs(int,char *);
void show_bstr(const char *);

int main(void)
{
	char bin_str[CHAR_BIT * sizeof(int) + 1];
	int number;
	
	puts("输入一个数字,我将把他转换为二进制(空一行结束):");
	while(scanf("%d",&number)==1)
	{
		itobs(number,bin_str);
		printf("%d 转换为二进制为",number);
		show_bstr(bin_str);
		putchar('\n');
	}
	puts("Bye!");
	
	return 0;
}
char * itobs(int n,char * ps)
{
	int i;
	const static int size = CHAR_BIT * sizeof(int);
	
	for(i=size-1;i>=0;i--,n>>=1)
		ps[i]=(01 & n) + '0';
		ps[size] = '\0';
		
		return ps;
}
void show_bstr(const char * str)
{
	int i = 0;
	while(str[i])
	{
		putchar(str[i]);
		if(++i % 4 == 0 && str[i])
			putchar(' ');
	}
}

(该代码摘自《C Primer Plus》)

这代码是我高中是学到位运算符时抄到U盘里的,现在全都忘光了,放这里权当参考。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值