递归6:【SSL】1564.2的幂次方
题目:
任何一个正整数都可以用2的幂次方表示.
例如:137=2^7 + 2^3 + 2^0
同时约定次方用括号来表示,即a^b可表示为a(b)
由此可知,137可表示为:2(7)+2(3)+2(0)
进一步:7=2^2 + 2 + 2^0 (2^1用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 + 1
所以1315最后可表示为:2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
输入
正整数(n<=10^15)
输出
符合约定的n的0,2表示(在表示中不能有空格)
输入样例
137
输出样例
2(2(2)+2+2(0))+2(2+2(0))+2(0)
思路:
看到这道题目第一时间大家一定会想到位运算,但是用位运算该怎么做呢?我一开始也是想了很久都没想出递归方法,后来想到用数组来存2的每个幂,然后每次就去找、递归当前这个数还能不能分出来,一直到他小于等于2就结束递归,但是后来却发现这个是错的(其实这样做也行,只是我没处理好),就换了另一种方法:
再讲之前先说一下一个内置函数:s=log x(n),这个函数是用来快速开n的x次方的,比如 int log2(10)=3,因为 8是最大的不超过10的2的幂次方。
有了这个之后我们每次递归的时候就先求出s的,然后再求2的x次方(w),如果w不为2的话说明当前这个数还可以分解,就输出“2(”,再进行递归,再输出“)”,如果n-w大于0,那就说明还可以分解,再接着递归,直到w为2或n=0的时候就结束递归(n=1的话那么w就等于0,再进行递归的话n就等于0了)。
PS:因为数据太大,要用long long存。
代码:
#include<bits/stdc++.h>
using namespace std;
long long n;
void dg(long long x)
{
if(x==0)
{
cout<<"0";
return ;
}
long long w=log2(x);
long long t=pow(2,w);
if(t==2)
cout<<"2";
else
{
cout<<"2(";
dg(w);
cout<<")";
}
if(x-t>0)
{
cout<<"+";
dg(x-t);
}
}
int main()
{
cin>>n;
dg(n);
return 0;
}