题目
任何一个正整数都可以用2的幂次方表示。例如:
137=27+23+2^0
同时约定幂次方用括号来表示,即ab 可表示为a(b)。
由此可知,137可表示为:
2(7)+2(3)+2(0)
进一步:7= 22+2+20 (21用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+2^0
所以1315最后可表示为:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
输入:正整数(n≤20000)
输出:符合约定的n的0,2表示(在表示中不能有空格)
输入格式 Input Format
一个正整数
输出格式 Output Format
符合约定的n的0,2表示(在表示中不能有空格)
样例输入 Sample Input
73
样例输出 Sample Output
2(2(2)+2)+2(2+2(0))+2(0)
分析
对于一个输入的数m对其不断除以2,统计轮数,直到m被除到1时结束统计。以14为例,先将其化为2(3)+2(2)+2(0).首先处理如何输出2(3)部分,14被2整除一共经历了三轮。关键是剩下的部分“+2(2)+2(0)”如何处理呢?下面简单列出一个推导过程寻找规律:
除了可以观察到14被整除了三轮,直接写上2(3)。后面加+的部分其实可以在递归结束后回溯实现。第三轮时,出现了余1,统计之前的轮数r=2,故填上“+2(2)”,回溯接着往上,第二轮再次出现了余1,统计之前的轮式r=1,故填上“+2(1)”。为了陈述方便,就举一个比较小的数做例子。其他数字也是一样的规律。
接下来一个问题,便是如何对括号内的轮数进一步分解呢?2(3)里的3继续分解?在递归结束时,继续递归,这次是以轮数r为参数继续递归,即fun(r,0),在后面的”+”的添加部分(即代码的else部分)继续递归。当然需要考虑当数m分别为0、1、2时输出情况不同的情况。
package transferjinzhi;
import java.util.Scanner;
public class Trst04 {
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
System.out.print("输入");
int m=scan.nextInt();
fun(m,0);
}
private static void fun(int m,int r) {
if(m==1)//递归结束
{
//System.out.print("2("+r+")");
switch (r) {
case 0:
System.out.print("2(0)");
break;
case 1:
System.out.print("2");
break;
case 2:
System.out.print("2(2)");
break;
//处理括号内大于2可在分解的情况
default:
System.out.print("2(");
fun(r,0);//拿轮数继续分解 递归
System.out.print(")");
break;
}
return;
}
else
{
//一直除2,除一次加一次轮数,比如处理14 14一直除以2直到无法整除时记录最大轮数3
fun(m/2, r+1);
//是否余数为1 前面完后,剩下的6是在回溯时加的
if(m%2==1)
{
switch (r) {
case 0:
System.out.print("+2(0)");
break;
case 1:
System.out.print("+2");
break;
case 2:
System.out.print("+2(2)");
break;
//处理括号内大于2可在分解的情况
default:
System.out.print("+2(");
fun(r,0);//拿轮数继续分解 递归
System.out.print(")");
break;
}
//System.out.print("+2("+r+")");
}
}
}
}
运行结果