C/C++洛谷---P1010 [NOIP1998 普及组] 幂次方

个人主页:

小白,请指教。_小项目,数据结构,选择题-CSDN博客

专题分栏:洛谷刷题

https://blog.csdn.net/qq_73435980/category_12427681.html

题目链接:P1010 [NOIP1998 普及组] 幂次方 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

目录

一、题目

题目描述

输入格式

输出格式

输入输出样例

说明/提示

二、题解

1.老规矩,还是先对题目进行分析:

2.代码的逐步编写:

第一步:任何一个正整数都可以用 2 的幂次方表示。根据示例137=2^7+2^3+2^0。我们也同样,先把正整数拆开成上述格式。

第二步:如何将括号里面的数也转化为关于2的次幂方之和

最后:合并

3.运行结果 


一、题目

题目描述

任何一个正整数都可以用 2 的幂次方表示。例如 137=2^7+2^3+2^0。

同时约定方次用括号来表示,即a^b 可表示为 a(b)。

由此可知,137 可表示为 2(7)+2(3)+2(0)

进一步:

7=2^2+2+2^0 ( 2^1 用 2 表示),并且 3=2+2^0。

所以最后 137 可表示为 2(2(2)+2+2(0))+2(2+2(0))+2(0)2(2(2)+2+2(0))+2(2+2(0))+2(0)。

又如 1315=2^10+2^8+2^5+2+1

所以 1315 最后可表示为 2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)。

输入格式

一行一个正整数 n。

输出格式

符合约定的 n 的 0,2 表示(在表示中不能有空格)。

输入输出样例

输入                         输出

1315             2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

说明/提示

【数据范围】

对于 100% 的数据,1≤n≤2×10^4。

二、题解

1.老规矩,还是先对题目进行分析:

这个题目比较简洁,题目内容比较简单。要注意的就是2^1用2表示,不需要写括号,1用2(0)表示。

2.代码的逐步编写:

第一步:任何一个正整数都可以用 2 的幂次方表示。根据示例137=2^7+2^3+2^0。我们也同样,先把正整数拆开成上述格式。

#include<stdio.h>
#include<math.h>
int main()
{
	int n;
	scanf("%d", &n);//所求的数
	int flag = n % 2;//奇偶数标记:判断一下奇偶数
	while (n)//把n逐层的拆开
	{
		int i = 0;
		while (n >= (int)pow(2, i))//寻找一下比n大的最小2的次幂数,i为最小2的次幂数的指数
			i++;
        //判断结束标志
		if ((n - (int)pow(2, i - 1) == 0) || (flag == 1 && i - 1 == 0))//i-1为在1~n的范围内最大2的次幂数,因为pow函数默认的是double类型,而n为整型,所以将pow强制类型转化
		{
			if (i - 1 > 1)
			{
				printf("2(%d)", i - 1);
			}
			else if (i - 1 == 1)
			{
				printf("2");
			}
			else
			{
				printf("2(0)");
			}
		}
		else
		{
			if (i - 1 > 1)
			{
				printf("2(%d)+", i - 1);
			}
			else if (i - 1 == 1)
			{
				printf("2+");
			}
			else
			{
				printf("2(0)+");
			}
		}
		n -= (int)pow(2, i - 1);//把最大的2的次幂数减掉,得到剩余的数,然后再进行上述步骤进行分割
	}
	return 0;
}

运行结果=============================

如果没有下面的条件语句的话,会出现bug

if ((n - (int)pow(2, i - 1) == 0) || (flag == 1 && i - 1 == 0))

因为137=2^7+2^3+2^0是用’+‘相连的

如果代码只有else部分:最后还会出现’+‘,这是不必要的,所以需要判断什么时候是最后一个2的次幂方数。

而根据思考,当剩余的数正好是2的次幂方的时候,或者如果剩余的数正好是1的时候,没有办法继续往下分,所以条件就是把上述的话编译成代码即可。

第二步:如何将括号里面的数也转化为关于2的次幂方之和

现在的运行结果里最终答案已经接近了。

此时,我们为了简便main函数里面的代码量,我选择用函数的方式,完成这项功能。

和前面一样,像把大的数化简为2的次幂方之和的数一样,我们也用相同的思维,来完成函数

 在代码编写前,我们需要确定函数的名称,参数,返回值。名称我就用test01来编写(用其他的也行,这个没有什么要求)。参数,我们需要的是将括号里面2的次幂转化成0,2格式,所以,我们不妨用括号里面的数当作参数(137=2(7)+2(3)+2(0),就比如这里的7,3)。返回值,我们只需要打印,所以就直接用void类型。

void test01(int n)
{
	if (n > 1)//首先,他本来就是次幂,所以,我们需要一开始就对其进行判断,如果不判断的话就会出现2(1)这中情况的出现
	{
        //下面大体和main函数里面的一样
		int flag = n % 2;
		while (n)
		{
			int i = 0;
			while (n >= (int)pow(2, i))
				i++;
			if ((n-(int)pow(2,i-1)==0 ) || (flag == 1 && i - 1 == 0))
			{
				if (i - 1 > 1)
				{
					printf("2(");
					test01(i - 1);//这里采用递归的方式,防止拆一次拆不彻底,就比如n=8,第一次拆会出现2(3),而3也能进行下次的拆分
					printf(")");
				}
				else if (i - 1 == 1)
				{
					printf("2");
				}
				else
				{
					printf("2(0)");
				}
			}
			else
			{
				if (i - 1 > 1)
				{
					printf("2(");
					test01(i - 1);
					printf(")+");
				}
				else if (i - 1 == 1)
				{
					printf("2+");
				}
				else
				{
					printf("2(0)+");
				}
			}
			n -= (int)pow(2, i - 1);
		}
	}
	else if(n==1)
	{
		printf("2");
	}
	else 
	{
		printf("2(0)");
	}
}

最后:合并

主要的步骤都已经弄完了,只需要把上述两部分合并即可。

#include<stdio.h>
#include<math.h>
void test01(int n);//函数声明
int main()
{
	int n;
	scanf("%d", &n);
	int flag = n % 2;
	while (n)
	{
		int i = 0;
		while (n>=(int)pow(2,i))
			i++;
		if ((n - (int)pow(2, i - 1) == 0) || (flag == 1 && i - 1 == 0))
		{
			if (i-1 > 1)
			{
				printf("2(");
				test01(i - 1);对函数的调用
				printf(")");
			}
			else if(i-1 == 1)
			{
				printf("2");
			}
			else
			{
				printf("2(0)");
			}
		}
		else
		{
			if (i - 1 > 1)
			{
				printf("2(");
				test01(i - 1);
				printf(")+");
			}
			else if (i - 1 == 1)
			{
				printf("2+");
			}
			else
			{
				printf("2(0)+");
			}

		}
		n -= (int)pow(2, i - 1);
	}
	return 0;
}
void test01(int n)
{
	if (n > 1)
	{
		int flag = n % 2;
		while (n)
		{
			int i = 0;
			while (n >= (int)pow(2, i))
				i++;
			if ((/*0 == flag*/n-(int)pow(2,i-1)==0 ) || (flag == 1 && i - 1 == 0))
			{
				if (i - 1 > 1)
				{
					printf("2(");
					test01(i - 1);
					printf(")");
				}
				else if (i - 1 == 1)
				{
					printf("2");
				}
				else
				{
					printf("2(0)");
				}
			}
			else
			{
				//printf("2(%d)+", i - 1);
				if (i - 1 > 1)
				{
					printf("2(");
					test01(i - 1);
					printf(")+");
				}
				else if (i - 1 == 1)
				{
					printf("2+");
				}
				else
				{
					printf("2(0)+");
				}
			}
			n -= (int)pow(2, i - 1);
		}
	}
	else if(n==1)
	{
		printf("2");
	}
	else 
	{
		printf("2(0)");
	}
}

3.运行结果 

 谢谢大家支持!!!

让我们共同进步。

  • 15
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仍有未知等待探索

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值