您的位置:首页 > 其它

POJ 1906 Three Powers

2009-11-28 11:20 274 查看
Three powers

Time Limit: 1000MSMemory Limit: 30000K
Total Submissions: 3299Accepted: 1405
Description
Consider the set of all non-negative integer powers of 3.
S = { 1, 3, 9, 27, 81, ... }
Consider the sequence of all subsets of S ordered by the value of the sum of their elements. The question is simple: find the set at the n-th position in the sequence and print it in increasing order of its elements.
Input
Each line of input contains a number n, which is a positive integer with no more than 19 digits. The last line of input contains 0 and it should not be processed.
Output
For each line of input, output a single line displaying the n-th set as described above, in the format used in the sample output.

Sample Input
1
7
14
783
1125900981634049
0

Sample Output
{ }
{ 3, 9 }
{ 1, 9, 27 }
{ 3, 9, 27, 6561, 19683 }
{ 59049, 3486784401, 205891132094649, 717897987691852588770249 }

Source
Waterloo local 2004.06.12
/*
终于用到了自己写的大数运算工具,呵呵,很兴奋啊,需要的可以去我的资源里下载
思路主要是:
(1)对于数列{空, 1, 3, 9, 27, 81, ...}一直到3 ^ 64, 先分别利用大数工具计算出num3[i], exp3[i]
exp3[i]就是数列3 ^ i, num3[i] = 2 ^ i,表示以 1 - i个数可以组成的子集合的个数
(2)对于输入val从第一位往高位寻找, 直到num3[pos] >= val, 则这个pos表示1-pos位的某个子集可以组
成第val个集合
(3)接下来需要判断1-pos位中那几位是在目标集合中的。从pos往低位处理,假设当前处理到了第p位
则如果val > num3[p - 1],则表示集合的构成离不开p,所以将exp3[p]加入目标集合中,同时val -= num3[p - 1];
然后p--,往下处理
(4)最后输出结果即可
注意的是空集,也就是val = 1需要单独处理
*/

#include <iostream>
#include <cmath>
#include <string>
#define MAX_L 64
using namespace std;

string exp3[MAX_L + 1];
string num3[MAX_L + 1];
int res[MAX_L + 1], len;

/*
以下是我写的大数运算工具,需要全套工具的可以去我的资源里面下载
*/
/**
* This function return a reverse string for a given string
* Modifer1: 2009.06.13 Finish the first edition of getReverse
*/
string getReverse(string str)
{
string revStr = "";
int pos = static_cast<int>(str.length()) - 1;
for(; pos >= 0; pos--)
revStr += str[pos];
return revStr;
}

/*大数比较*/
int bigIntegerCmp(string left, string right)
{
int lenl = static_cast<int>(left.length());
int lenr = static_cast<int>(right.length());
if(lenl < lenr)
return -1;
else if(lenl > lenr)
return 1;
return strcmp(getReverse(left).c_str(), getReverse(right).c_str());
}

/*大数乘法*/
string bigIntegerMult(string left, string right)
{
int minLen = static_cast<int>(left.length());
int maxLen = static_cast<int>(right.length());
string longerStr = "";
string shorterStr = "";
string res = "";
//get the longer and short strings and corresponded length
if(left.length() <= right.length())
{
minLen = static_cast<int>(left.length());
maxLen = static_cast<int>(right.length());
shorterStr = left;
longerStr = right;
}
else
{
minLen = static_cast<int>(right.length());
maxLen = static_cast<int>(left.length());
shorterStr = right;
longerStr = left;
}
int pos1 = 0;
int pos2 = 0;
//start from the first digit of the shorter string
for(pos1 = 0; pos1 <= minLen - 1; pos1++)
{
//multiply each digit of the longer string
int residue = 0, product = 0, quotient = 0;
int curPos = 0;
for(pos2 = 0; pos2 <= maxLen - 1; pos2++)
{
curPos = pos1 + pos2;
//new space
if(res.length() == 0 || curPos > int(res.length() - 1))
{
product = (shorterStr[pos1] - '0') * (longerStr[pos2] - '0') + quotient;
quotient = product / 10;
residue = product % 10;
res += residue + '0';
}
//space already exists, just add the original value to product
else
{
product = (shorterStr[pos1] - '0') * (longerStr[pos2] - '0') + quotient + (res[curPos] - '0');
quotient = product / 10;
residue = product % 10;
res[curPos] = residue + '0';
}
}
//process the extra quotient
//start position
curPos = maxLen + pos1;
while(quotient != 0)
{
if(res.length() == 0 || curPos > int(res.length() - 1))
{
residue = quotient % 10;
quotient = quotient / 10;
res += residue + '0';
}
else
{
quotient = quotient + (res[curPos] - '0');
residue = quotient % 10;
quotient = quotient / 10;
res[curPos] = residue + '0';
}
curPos++;
}
}
//std::cout<<res.length()<<std::endl;
return res;

}

/*大数减法*/
string bigIntegerSub(string left, string right)
{
string biggerStr = "";
string smallerStr = "";
string res = "";
int minLen = 0;
int maxLen = 0;

//get the bigger integer and smaller integer
int cmpRes = bigIntegerCmp(left, right);
if(cmpRes == -1 || cmpRes == 0)
{
smallerStr = left;
biggerStr = right;
}
else
{
smallerStr = right;
biggerStr = left;
}
//get related size
minLen = static_cast<int>(smallerStr.length());
maxLen = static_cast<int>(biggerStr.length());

int extra = 0, temp = 0, subRes = 0;
//subtraction operation, first part
int pos1;
for(pos1 = 0; pos1 <= minLen - 1; pos1++)
{
int curL = biggerStr[pos1] - '0';
int curR = smallerStr[pos1] - '0';
temp = 0;
while((subRes = (curL - curR + 10 * temp - extra)) < 0)
temp++;
res += subRes + '0';
extra = temp;
}
//subtraction operation, second part
for(int pos2 = pos1; pos2 <= maxLen - 1; pos2 ++)
{
int curL = biggerStr[pos2] - '0';
temp = 0;
while((subRes = (curL + 10 * temp - extra)) < 0)
temp++;
res += subRes + '0';
extra = temp;
}
//remove the zero at head
while(res[res.length() - 1] == '0' && res.length() >= 2)
res = res.substr(0, res.length() - 1);

//std::cout<<"res size:"<<res.length()<<std::endl;
return res;
}

int main()
{
int i;
exp3[1] = "1";
num3[0] = "1";
for(i = 1; i <= MAX_L; i++)
{
if(i != 1) exp3[i] = bigIntegerMult(exp3[i - 1], "3");
num3[i] = bigIntegerMult(num3[i - 1], "2");
//cout<<num3[i]<<endl;
}
string val;
while(cin>>val && val != "0")
{
len = 0;
int pos = 0;
if(val != "1")
{
val = getReverse(val);
//寻找pos使得num3[pos] >= val
while(bigIntegerCmp(num3[pos], val) < 0) pos++;
//从pos往下处理,寻找目标集合的元素
while(bigIntegerCmp(val, "0") != 0 && pos > 0)
{
if(bigIntegerCmp(val, num3[pos - 1]) > 0)
{
res[len++] = pos;
val = bigIntegerSub(val, num3[pos - 1]);
}
pos--;

}
cout<<"{";
for(pos = len - 1; pos >= 0; pos--)
{
cout<<" ";
cout<<getReverse(exp3[res[pos]]);
if(pos != 0) cout<<",";
}
cout<<" }"<<endl;
}//空集需要单独处理
else cout<<"{ }"<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: