一 题目描述
二 示例及提示
输入格式
一行一个正整数 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)
三 题解
1.直接按题意递归处理
思路:
代码:
#include <iostream>
#include <cmath>
using namespace std;
const int a = 2;
void confirm(int x)
{
// 先无脑输出一个2,因为输入范围不存在小于1的数
if(x != 0)
cout<< "2";
else return;
// 先找最接近x的k次幂
int k = log(x)/log(a);
//处理k部分 讨论k=1 =2 =0 和其他情况
if(k == 2){
cout << "(2)";
}else if(k == 0){
cout << "(0)";
}else if(k > 2){
// 若次幂大于2,则也要递归处理
cout << "(";
confirm(k);
cout << ")";
// 注意括号的先后输出
}
// 余数remainder
int remainder = x - pow(a,k);
// 处理余数部分
if(remainder){
cout << "+";
confirm(remainder);
}
}
int main()
{
int x;
cin >> x;
confirm(x);
return 0;
}
另:
exp(n) 为e^n;
log() 以e为底
log10() 以10为底
2.二进制+递归
以下题解基本来自洛谷原题里的题解区Delva大佬的解答。
#include <iostream>
using namespace std;
string confirm(int x)
{
if(x == 0)
return "0";
int i = 0;
string s = "";
do{
if(x & 1){
s = (i == 1? "2":"2("+confirm(i)+")") + (s == ""? "":"+") + s;
}
}while(i++,x>>=1);
return s;
}
int main()
{
int x;
cin >> x;
cout << confirm(x) ;
return 0;
}
写了一点我理解的思路就是:首先要明白二进制就是表示一个正整数分解为2的幂次方和,然后对于用户输入的数字x,我们可以让x每次右移1,同时设立一个计数器i来计算其右移的次数,而while的终止条件就是从低位到高位直到遍历完x的最高位,我们每次用字符串来保存遍历的结果,同时后一次遍历得到的字符串要拼接上前一次的字符串,并且要注意后一次的必须写在前面,因为它的次方更大。而且如果是遍历的第一遍,当字符串为空的时候,当然我们就不需要填写加号了,因此可以用三元运算符判断s是否为空串,如果是的话就不加加号,不是则需要加上。接下来是重点——对字符串拼接的设计,具体如图。
二进制位上的数不是1就是0,为0时不用做任何处理,因此我们只用考虑位上数字为1的情形。而且如图会发现,只有当i=1时,2后面是不用跟括号的,把这个情况做特殊处理,用一个三目运算符,讨论这两种情况,而括号里的数字我们则再进行递归处理,当i==0时,我们在函数开始部分用判断语句返回一个"0"。
注:>>= 相当于右移后赋值,例如x>>=3,就是将x右移3位后得到的结果再赋值给原来的变量x。