本文由Jzwalliser原创,发布在CSDN平台上,遵循CC 4.0 BY-SA协议。
因此,若需转载/引用本文,请注明作者并附原文链接,且禁止删除/修改本段文字。
违者必究,谢谢配合。
个人主页:blog.csdn.net/jzwalliser
题目
洛谷 P1010 [NOIP1998 普及组] 幂次方
[NOIP1998 普及组] 幂次方
题目描述
任何一个正整数都可以用 2 2 2 的幂次方表示。例如 137 = 2 7 + 2 3 + 2 0 137=2^7+2^3+2^0 137=27+23+20。
同时约定次方用括号来表示,即 a b a^b ab 可表示为 a ( b ) a(b) a(b)。
由此可知, 137 137 137 可表示为 2 ( 7 ) + 2 ( 3 ) + 2 ( 0 ) 2(7)+2(3)+2(0) 2(7)+2(3)+2(0)
进一步:
7 = 2 2 + 2 + 2 0 7= 2^2+2+2^0 7=22+2+20 ( 2 1 2^1 21 用 2 2 2 表示),并且 3 = 2 + 2 0 3=2+2^0 3=2+20。
所以最后 137 137 137 可表示为 2 ( 2 ( 2 ) + 2 + 2 ( 0 ) ) + 2 ( 2 + 2 ( 0 ) ) + 2 ( 0 ) 2(2(2)+2+2(0))+2(2+2(0))+2(0) 2(2(2)+2+2(0))+2(2+2(0))+2(0)。
又如 1315 = 2 10 + 2 8 + 2 5 + 2 + 1 1315=2^{10} +2^8 +2^5 +2+1 1315=210+28+25+2+1
所以 1315 1315 1315 最后可表示为 2 ( 2 ( 2 + 2 ( 0 ) ) + 2 ) + 2 ( 2 ( 2 + 2 ( 0 ) ) ) + 2 ( 2 ( 2 ) + 2 ( 0 ) ) + 2 + 2 ( 0 ) 2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0) 2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)。
输入格式
一行一个正整数 n n n。
输出格式
符合约定的 n n n 的 0 , 2 0, 2 0,2 表示(在表示中不能有空格)。
样例 #1
样例输入 #1
1315
样例输出 #1
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
提示
【数据范围】
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 2 × 10 4 1 \le n \le 2\times {10}^4 1≤n≤2×104。
NOIP1998 普及组 第三题
想法
虽然题目确实写得很清楚了,但是可以梳理一下这个过程。一起理解一下题目吧。以 137 137 137为例,有以下过程:
137 = 2 7 + 2 3 + 2 0 = 2 2 2 + 2 + 2 0 + 2 3 + 2 0 = 2 2 2 + 2 + 2 0 + 2 2 + 2 0 + 2 0 137=2^7+2^3+2^0=2^{2^2+2+2^0}+2^3+2^0=2^{2^2+2+2^0}+2^{2+2^0}+2^0 137=27+23+20=222+2+20+23+20=222+2+20+22+20+20。
所以嘛,数字 137 137 137最后表示为了 2 ( 2 ( 2 ) + 2 + 2 ( 0 ) ) + 2 ( 2 + 2 ( 0 ) ) + 2 ( 0 ) 2(2(2)+2+2(0))+2(2+2(0))+2(0) 2(2(2)+2+2(0))+2(2+2(0))+2(0)。
像这样的题目,一定是会想到写一个递归函数来处理这样的问题,这是最重要的。当然,本题也考察了数字转化为二进制。
实现
- 将数字转化为二进制。
- 拆分二进制,找出二进制中 1 1 1所在的位置。
- 递归重复以上过程,直到将数字拆分得只剩下 2 2 2和 0 0 0。
- 输出。
题解
C++
#include<bits/stdc++.h>
using namespace std;
string to_bin(int n){ //将十进制转换为2进制string digit = "01"; //位if(n == 0){return "";}return to_bin(n / 2) + digit[n % 2];
}vector<int> getbits(int n){ //获取二进制中1所在的位置string m = to_bin(n); //获取二进制reverse(m.begin(),m.end()); //反转,方便一会儿的遍历vector<int> bits; //建列表for(int i = 0;i < m.size();i++){ //遍历if(m[i] == '1'){ //找到二进制中1的位置bits.push_back(i); //记录下来}}return bits; //返回
}string split(int x){ //递归将数字拆分为只有2和0的形式vector<int> bits = getbits(x); //获取1所在的位置reverse(bits.begin(),bits.end()); //反转,低位先遍历,高位后遍历string str = ""; //记录for(int i = 0;i < bits.size();i++){str += '2'; //无论如何先整一个2上去if(bits[i] > 2){ //如果当前的位大于2str += '(' + split(bits[i]) + ')'; //那么需要拆}else if(bits[i] == 2){ //如果等于2str += "(2)"; //那就加个2}else if(bits[i] == 0){ //如果等于0str += "(0)"; //那就加个0}str += "+"; //记得放上加号}return str.substr(0,str.size() - 1); //因为在前面的处理中会导致字符串末尾有一个冗余的加号,所以需要去掉
}int main(){int num;cin >> num; //输入cout << split(num); //输出return 0;
}
Python
num = int(input()) #输入
def to_bin(n): #将十进制转换为2进制digit = "01" #获取二进制if n == 0:return ""return to_bin(int(n / 2)) + digit[n % 2]def getbits(n):m = to_bin(n)[::-1] #反转,方便一会儿的遍历bits = [] #建列表for i in range(len(m)): #遍历if m[i] == "1": #找到二进制中1的位置bits.append(i) #记录下来return bits #返回def split(x): #递归将数字拆分为只有2和0的形式bits = getbits(x) #获取1所在的位置string = "" #记录for i in reversed(bits): #反转,低位先遍历,高位后遍历string += "2" #无论如何先整一个2上去if i > 2: #如果当前的位大于2string += "(" + split(i) + ")" #那么需要拆elif i == 2: #如果等于2string += "(2)" #那就加个2elif i == 0: #如果等于0string += "(0)" #那就加个0string += "+" #记得放上加号return string[:-1] #因为在前面的处理中会导致字符串末尾有一个冗余的加号,所以需要去掉print(split(num)) #输出
难度
难度:★★☆☆☆
大概是没什么难度吧。主要是二进制和递归。其它迎刃而解。
结尾
欢迎Hack我的代码!记得评论区域留言哦!我们下期再见(˵¯͒〰¯͒˵)