P1010 [NOIP1998 普及组] 幂次方分治思想求解

题目链接:https://www.luogu.com.cn/problem/P1010

 题目描述:

任何一个正整数都可以用 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)。

又如 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)。

输入格式:

一行一个正整数n。

输出格式:

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

输入输出样例:

输入 #1

1315

输出 #1

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。

 

题目分析:

因为题目所给的数据最大不超过2万,所以还是比较好解决。

从题目说明和样例可以知道这道题大致是要用分治和递归去求解,将给定数字中最大的2的幂次方求出后再减去后再求出现在的最大的2的幂次方直至最后数字为0(求现在数字中最大的2的幂次方就体现出了分治的思想),再将所求得的最大幂次方分别进行处理,用递归判断其是否还能分成2的幂次方,最后把这些进行相加然后输出。

例如:7当中最大的2的幂次方为2^2,7减去4后为3,在3中最大的2的幂次方为2(2^1表示为2),3减去2后为1,在1中最大的2的幂次方为2^0,然后结束。

分析过后一步步进行解决!

代码片段:

int calculate(int n)//计算幂次方
{
	if (n == 0)//递归退出条件
		return 0;
	int i, k = 1, count = 0;//i和count为幂函数的指数部分,i为大于所求数字的最小的2的幂次方的指数,count为所求数字中的2的最大的幂次方的指数
	for (i = 1; i <= 15; i++)
	{
		k *= 2;
		count = i;
		if (k > n)
		{
			n -= k / 2;//当前n的值减去2的最大幂次方的值(因为2多乘了一次因此要/2)
			count--;
			break;
		}
	}
	if (n)//如果n有剩余继续分成小部分然后相加
	{
		cout << "+";//所分成的小部分相加
		return calculate(n);//继续处理剩余n的值
	}
	return 0;
}

代码分析:因为2的15次方为32768超出了所给范围,因此所求的最大的2的幂次方为2^14,因此1 < i <= 15,而count则大于0,小于等于14 ,假设给定数字为30,i就为5,因为2^5为32大于30,count为4,因为2^4为16小于30,30-16=14>0,因此继续分成其他小部分,直至数字变为0,但是如果count比较大就像4还可以看成2^2,这时该怎么办呢?不急,在后面加上递归的条件就行了,我用的是选择语句。

switch (count)
	{
	case 0:cout << "2(0)"; break;
	case 1:cout << "2"; break;
	default:cout << "2("; calculate(count); cout << ")"; break;//指数为其他情况时
	}

在for循环和if判断中间加上switch语句,判断是否需要递归。

整体代码(已AC):

 

 

#include <iostream>
using namespace std;
int calculate(int n)//计算幂次方
{
	if (n == 0)//n为0时退出
		return 0;
	int i, k = 1, count = 0;//i和count为幂函数的指数部分
	for (i = 1; i <= 15; i++)
	{
		k *= 2;
		count = i;
		if (k > n)
		{
			n -= k / 2;//当前n的值减去2的最大幂次方的值
			count--;
			break;
		}
	}
	switch (count)
	{
	case 0:cout << "2(0)"; break;
	case 1:cout << "2"; break;
	default:cout << "2("; calculate(count); cout << ")"; break;//指数为其他情况时
	}
	if (n)//如果n有剩余继续分成小部分然后相加
	{
		cout << "+";//所分成的小部分相加
		return calculate(n);//继续处理剩余n的值
	}
	return 0;
}
int main()
{
	int num;
	cin >> num;//输入想处理的数据
	calculate(num);
	return 0;
}

本题简单体现出分治和递归的思想。如果有问题,可以进行讨论交流。

计算机204 zjr

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值