题解 | 幂次方-牛客假日团队赛8L题

L-幂次方_牛客假日团队赛8

https://ac.nowcoder.com/acm/contest/1069/L

题目描述

任何一个正整数都可以用2的幂次方表示。例如:                  
        
同时约定方次用括号来表示,即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,那么说明他剩余部分也需要进行分解的,所以应该需要输出‘+’,例如 那么说明分解了7后 一定要有+号,才能把9部分的分解也加上。
#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;
}

方法三:打表法(作弊)
因为题目中数据规模是 ,所以如果 我们把指数0-14 的表示好放在一个字符串数组里面,如果来了一个数X,我们只需要把对应的幂次方直接输出即可。
#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
全部评论

相关推荐

去B座二楼砸水泥地:不过也可以理解,这种应该没参加过秋招
点赞 评论 收藏
分享
10-28 11:04
已编辑
美团_后端实习生(实习员工)
一个2人:我说几个点吧,你的实习经历写的让人觉得毫无含金量,你没有挖掘你需求里的 亮点, 让人觉得你不仅打杂还摆烂。然后你的简历太长了🤣你这个实习经历看完,估计没几个人愿意接着看下去, sdk, 索引这种东西单拎出来说太顶真了兄弟,好好优化下简历吧
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务