[NOIP1998 普及组] 幂次方
迪丽瓦拉
2025-05-28 11:43:03
0次

总时间限制: 

 

1000ms

内存限制: 

65536kB

题目描述:

任何一个正整数都可以用2的幂次方表示。例如:

    137=2^7+2^3+2^0

同时约定方次用括号来表示,即ab可表示为a(b)。由此可知,137可表示为:

    2(7)+2(3)+2(0)

进一步:7=2^2+2+2^0(21用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(n≤20000)。

输出:

一行,符合约定的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)

说明/提示

【数据范围】

对于 100% 的数据,1≤n≤2×10^4。

思路:

1.模拟递归

这个算法很多人都会写了,思路如下:

  1. 算出2的多少次幂最接近给出的n;
  2. 用原来n的数减去2的幂,如果这个数大于2,继续对新的n进行搜索;
  3. 如果幂大于2,对幂进行上述搜索;
  4. 一旦输入函数的数为0(2的0次幂)或1(2的1次幂)或2(2的二次幂),输出;

至此,思路就很清晰了,那么我就上代码吧(很多人都会了不详解了)

//认真看,杜绝抄袭 
#include
using namespace std;
int n;
void search(int x)
{if(n!=0){int p=1,q=0;printf("2");//每一次搜索都要输出2 //如果是1次幂就没必要写2(1),后面会说; while(x>=p){++q; p*=2;	}//计算幂,由于这里会多算一次,所以计数器q-1; --q;if(q==0 || q==2)printf("(%d)",q);//各种括号的判断if(q>=3){printf("("); search(q);printf(")");}x-=p/2;//上面计数器就是多算了一次,因此p也多乘了一个2; if(x)//输入的数x为真(最后分解完就成0了,变成假),输出"+"; {printf("+");search(x);}}
}
int main()
{scanf("%d",&n);search(n);return 0;//别忘了写;	
} 

 下面讲一种高级的:

2.二进制数

我们知道,二进制数表示的其实就是一个正整数分解成为2的幂次方和!

如3用二进制表示为 11 ,从右到左分别是第0位,第1位……

则3=2^1+2^0(只要二进制那位是一,就是2^(这一位))

再比如10 二进制是1010,则10=2^3+2^1;

大家自己体会一下

下面更高级的:位运算(其实也不高级,就是没人做)

不会位运算的就用上面那种吧,个人觉得位运算更快(普通14ms,位运算11ms)

位运算具体问度娘吧

思路如下:

  1. 遍历n的二进制(从地位到高位),用数组储存该位为1的位数;如1010(即10),先记录第1位是1,最后记录到第3位是1;
  2. 遍历完成后,对高位先进行处理(即原来为i++,现在变为i--)
  3. 该位(就是幂的次数)大于2,,递归再次处理
  4. 一旦处理到该位小于3,输出;

这里着重点一下括号的添加:

  1. 在每一次递归搜索前,肯定是搜到2的几次幂,输出"2(";
  2. 搜索结束后,也有括号")",但这里也肯定有个"+";
  3. 最后一个不能输出加号,要进行判断,具体看下面程序;
  4. 是最后一个不要"+",不是就写个"+";
  5. 输入函数的幂小于3时,只要该次幂不等于1,输出(该次幂)
  6. 由于2的一次幂不会有括号,因此2的加号也不见了,特判幂=1;
  7. 同第3、4,只要2不是最后一个,输出"2+",是最后一个输出"2";

二进制代码实现如下:

//认真看,杜绝抄袭 
#include
using namespace std;
void ASCII(int m)
{int i=0,k=m,u=0,h[50];while(k)//位运算实现;{if(k&1)h[++u]=i;//h[++u]相当于++u,h[u]…… k>>=1;i++;}//据上面写的,u从1开始,无论如何一定会有输出; while(u)//u为真 {if(h[u]<3)//具体括号判断;{if(h[u]==1 && u-1!=0)  printf("2+");else if(h[u]==1)	   printf("2");if((h[u]==0||h[u]==2)&&(u-1!=0))  printf("2(%d)+",h[u]);else if(h[u]==0||h[u]==2)		  printf("2(%d)",h[u]);	--u;//搜索下一个;}else{printf("2(");ASCII(h[u--]);//相当于h[u],--u; //这里千万不能写成 h[--u],否则你会3个WA两个MLE; if(u!=0)printf(")+");//由于u进行了自减,此时的u已经是下一个数了; else printf(")");//判断括号;}	}
}
int main()
{int n;scanf("%d",&n);ASCII(n);return 0;//别忘了写;
}

总结:

  这道题并不怎么难,只需要基本的算法就可以解决,难点是输出括号和加号的时候容易出错 。

题目链接:

https://www.luogu.com.cn/problem/P1010icon-default.png?t=N176https://www.luogu.com.cn/problem/P1010

相关内容

热门资讯

亮眼数据盘点国庆假期蓬勃活力 ... 央视网消息:为期七天的国庆假期10月8日结束了,交通运输部表示,今年国庆假期人员流动量保持平稳,全社...
国庆假期家国同庆 河南文旅掀起... 大象新闻·河南交通广播记者:雷静 佑龙弦歌载庆,川原呈秀。2026年国庆假期,全省文化和旅游系统深入...
处处都是可感、可触、可参与的文... 来源:中国文化报本报记者集体采写国庆假期,全国处处涌动着文化科技热潮,各地花样翻新,推出“文旅+科技...
闪电评论 | 不负山海辽阔 金秋十月,山海辽阔,大地澎湃。长风从鲁西运河黄河岸边的县域市集,吹向省会城市潮流烟火街区,又掠过胶东...
旅游不只看风景了:年轻人开始“... 这个假期,年轻人旅游又整出了新花样:不光出去玩,还顺便报个课。数据显示,国庆期间,徒步、采摘、陶艺、...
兰州近郊轻徒步成国庆出游新风尚 金秋送爽,天朗气清。国庆假期,褪去了往年长途拥堵、景区扎堆的传统出游模式,兰州市民的过节方式悄然发生...
国庆假期河南重点景区共接待游客... “河南发布”消息,今年国庆假期,河南全省活动丰富、政策加力、场景焕新。重点监测零售企业累计实现销售额...
国庆假期中外旅游“双向奔赴”   新华社北京10月7日电 2026年国庆假期,中国游客走出国门,欣赏远方的风景;而外国游客从世界各...
长假尾声 游兴不减 10月7日,游客在浙江杭州西湖风景区游览。 新华社记者 徐昱 摄  国庆长假进入尾声,人们赏美景,品...
这座晋南古镇,在保护与烟火中复...   新华社太原10月7日电(记者邓浩然)“这有什么看头?”自幼在山西襄汾汾城长大的郑彦文,曾经面对汹...