洛谷 P1010 幂次方

题目描述
任何一个正整数都可以用22的幂次方表示。例如

137=27+23+2^0 137=2
7
+2
3
+2
0

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

由此可知,137137可表示为:

2(7)+2(3)+2(0)2(7)+2(3)+2(0)
进一步:

7= 22+2+207=2
2
+2+2
0

(2^1用2表示),并且

3=2+2^03=2+2
0

所以最后137137可表示为:

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+11315=2
10
+2
8
+2
5
+2+1
所以13151315最后可表示为:

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≤20000)n(n≤20000)。

输出格式:
符合约定的nn的0,20,2表示(在表示中不能有空格)

输入输出样例
输入样例#1: 复制
1315
输出样例#1: 复制
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

开始想法是把n先分解成多个幂指和,然后再把每个幂指和分解成题目要求的2的0次方,2的1次方,2的平方。(这应该就是种分治思想,把一个问题分解成多个子问题)但是在实现过程中遇到点小困难。。。
首先把n分解成幂指和很容易,先找出最大的比n小的幂,然后让n减去这个幂,继续分解,再把每个分解出的幂按分解n的规则分解,但是!!。。。第二次分解后还需要继续分解怎么办?再来一次?那要是分解出来又要继续分解。。那可麻烦了。。
那如何解决呢?
既然要分解这么多次,能不能用递归来实现分解幂次大于2的数的输出呢
粗略一想应该可以,每次遇到幂次大于2的数的时候递归,直到输出都在2次幂及以下。
所以最后代码的实现方法就是分治+递归。分治体现在把n分解成多个幂次,然后解决每个幂次(一个问题,分解成多个子问题),递归体现在在解决每个子问题时,如果还需要分解成多个子问题,用递归的方式实现。
最后代码如下(有参考成分。。嘤)

#include <stdio.h>
int a[20]; //用数组把小于20000 的2的幂指存一下,免得每次判断都得重新循环计算
void divide(int n)
{
	int i=0;
	if(n)
	{
		while(n>=a[i]) i++; //找出最小的比n大的幂次
		i--; //得出最大的比n小的幂次
		n=n-a[i]; //让n减去这部分,然后后面输出这部分的结果
		printf("2"); 
		if(i!=1) printf("("); //2的一次方不是2(1),而是2,如果幂次为1,就直接输出个2,没有后续
		if(i==0||i==2) printf("%d)",i); //如果幂次为0,2,要输出2(0)或2(1)(注意前面已经输出一个(了)
		if(i>=3){ //如果幂次大于等于3,先递归,再补上括号。
			divide(i);printf(")");
		}
		if(n!=0) { 再最后一大项之前都要输出一个+号连接,然后继续调用函数
			printf("+");divide(n);
		}
	}
}
int main()
{
	int n;
	scanf("%d",&n);
	a[0]=1;
	for(int i=1;i<=15;i++)
	 a[i]=a[i-1]*2;
	divide(n); //直接调用函数输出
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43332389/article/details/84961046