题目描述
任何一个正整数都可以用2的幂次方表示。例如:
同时约定方次用括号来表示,即a
可表示为
。
由此可知,137可表示为:

进一步:
(
用
表示)
同时约定方次用括号来表示,即a
由此可知,137可表示为:
进一步:
所以最后
又如:
所以
输入描述:
正整数
输出描述:
符合约定的n的0,2表示(在表示中不能有空格)
示例1
输入
1315
输出
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
解答
问题分析:方法一:将n拆分为若干2的幂次方的和,再将各个幂次方(指数)拆分成为若干2的幂次的和……这是递归的思想。递归的边界是什么呢?指数 n=0时候 直接输出2(0),n=1的时候输出 2。如果n>1的时候 那么应该直接输出“2(“,再对指数进行递归,递归后补上括号“)”(类似回溯恢复现场) 整个递归的过程类似于深度优先搜索(DFS)。+号的处理是本题的难点 ,什么时候输出 ‘+’号呢,如果X- 2n不为0,那么说明他剩余部分也需要进行分解的,所以应该需要输出‘+’,例如
#include<bits/stdc++.h>
using namespace std;
int x,a[32];
void npow(int n){
for(int i=x;i>=0;--i){
if(a[i]<=n){
n=n-a[i];
if(i>1){
cout<<"2(";
npow(i); //可以理解为DFS搜索
cout<<")"; //回溯
}
if(i==1) cout<<"2";
if(i==0) cout<<"2(0)";
if(n!=0) cout<<"+"; //若此n还没分解完,则后面还有项,所以输出一个+号
}
}
}
int main()
{
int n;
cin>>n;
a[0]=1;
while(a[x]<n){
x++;
a[x]=a[x-1]*2;
}
npow(n);
cout<<endl;
return 0;
}
方法二:分治的思想,把一个数X分解为
和
进行递归求解,这样可以简单的处理好“+”号的问题。
#include<bits/stdc++.h>
using namespace std;
string f(int x){
if (x==1) return "2(0)";
if (x==2) return "2";
if (x==3) return "2+2(0)"; //防止3 输出2(2(0))+2(0);
int n=log2(x); // 求出指数取整
int t=pow(2, n);
if (x==t) return "2("+f(n)+")"; // x 恰好是 2的n次放,后面就没有了 不需要+号。
else return "2("+f(n)+")+"+f(x-t); //不是2的n次方,那么对2部分分别进行递归求解用+号连接
}
int main(){
int x;
cin>>x;
cout<<f(x)<<endl;
} 方法三:打表法(作弊)
因为题目中数据规模是
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
string s[16]={"2(0)","2","2(2)","2(2+2(0))","2(2(2))","2(2(2)+2(0))","2(2(2)+2)",
"2(2(2)+2+2(0))","2(2(2+2(0)))","2(2(2+2(0))+2(0))","2(2(2+2(0))+2)",
"2(2(2+2(0))+2+2(0))","2(2(2+2(0))+2(2))","2(2(2+2(0))+2(2)+2(0))",
"2(2(2+2(0))+2(2)+2)","2(2(2+2(0))+2(2)+2+2(0))"};
bool temp=0;
for(int i=15;i>=0;i--)
if(pow(2,i)<=n)
{
n-=pow(2,i);
if(temp)
cout<<'+';
cout<<s[i];
temp=1;
}
return 0;
} 来源:qq_37358013

京公网安备 11010502036488号