Description:
J王国的货币非常奇怪,面值都是3的若干次方 即面值为1,3,9,27,81......... 国王现在发现这些货币,每种只有一张这样的钱。 于是国王发现从这些钱中先任意组合,再加钱的面值相加得到一个总和的话:
则面值最小的为空集,也就是说一张钱也不要
面值第2小的为{1},总和为1
面值第3小的为{3},总和为3
面值第4小的为{1,3},总和为4
面值第5小的为{9},总和为9
面值第6小的为{1,9},总和为10
面值第7小的为{3,9},总和为12
现在问你面值第K小的,它是选择了哪些钱币?
Input
一行给出一个数字k,1<N<=10^6
Output
输出若干行,每行输出一个数字,数字从小到大。
思路:
因题目限定为每种钱币只能是一张,也就是说某个数转为三进制后,只要找出该数中每位数字上的“1”,然后进行以3为底的幂次运算,即可达到题目要求的钱币组合。但问题的关键是如何找出第K小的数?同样由于题意,每种钱币只能使用1张或0张的组合,这就将问题变成了:一个n位的数,每位数只能使用0或1的排列组合方式,从小到大排列就是0、1、10、11、100、101......这就相当于是从小到大的二进制排列。刚好符合题意中的第K小的数,需要注意的是0变成了第一小,那么第K小就是K-1。分解K-1为二进制序列,再将该序列不同数位上的“1”进行以3为底、数位顺序为幂次进行幂运算即为答案!
AC代码:
#include<bits/stdc++.h>
using namespace std;
int pow(int a, int b) { //快速幂函数
int res = 1;
while (b > 0) {
if (b & 1) res *= a;
b >>= 1;
a *= a;
}
return res;
}
string Binary(int num) { //位操作将一个数分解为二进制数为字符串形式
string bit, s = "";
while (num > 0) {
bit = to_string( num & 1); // 获取最低位
s += bit ;
num >>= 1; // 右移一位
}
return s;
}
int main() {
int n;
cin >> n;
string bStr = Binary(n - 1); //返回逆序的二制字符串
for (int i = 0; i <= bStr.length(); ++i) //计算3的幂次
if (bStr[i] == '1')
cout << pow(3, i) << endl;
return 0;
}