来源:NOIP1998普及组
难度:普及-
算法标签:分治
题目描述
任何一个正整数都可以用 2 的幂次方表示。例如 137=2^7+2^3+2^0。
同时约定方次用括号来表示,即 a^ba可表示为 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。
输出格式
符合约定的 nn的 0, 2 表示(在表示中不能有空格)。
递归&分治的第一道题就着实把我难住了 。分析题目可知题目为分治,即把一个大数分成由有限个2的幂次方,且要求2的幂指数为0或1其中一种。初步考虑定义递归函数string dc(),然后在主函数中输出。于是先编写了一个主函数:
int main() {
int n;
cin>>n;
cout<<dc(n);
return 0;
}
只需编写分治函数dc()即可。
初代版本如下:
string dc( int a ){
int sum;
string ret;
for( int i=0 ; pow(2,i)<=a ; i++ )
if( pow(2,i+1)>a ){
if( i==0 )
ret="2(0)";
if( i==1 )
ret="2";
if( i==2 )
ret="2(2)";
if( i>2 ){
ret="2(";
ret+=dc(i-1);
ret+=")";
}
sum=pow(2,i-1);
}
int b=a-sum;
if( b!=0 ){
ret+="+";
ret+=dc(b);
}
return ret;
}
想法很简单,幂指数为0、1、2时均无需再调用函数,指数大于3时则再次调用。这里用到了字符串合并,用法如下:
string str="abc";
str+="def";
//此时str为“abcdef”
然而测试时输入15及以下的数均输出2(2),16以上均超出内存。于是开始捉虫。
第一个虫是编译器帮忙找出来的,if里用的是=,应改为“==”。怪不得超限,这是一个低级错误。
其次sum=pow(2,i-1)以及递归的ret+=dc(i-1)中参数判断错误,应把i-1改为i。此错误可通过调试找出。
在此基础上在进行测试,发现全部满足,于是提交AC。提交记录
AC代码不再展示,只需按照上述修改即可。
递归&分治 ………………………………………………………………………………(1/15)
2022.8.27