这道题原意是输入一个整数,然后将其分解为若干个数字的和,例如:
5 = 5
5 = 4 + 1
·
·
·
5 = 1 + 1 + 1 + 1 + 1
于是这样就形成了一个集合:
enum(5)-> [[5],[4,1],[3,2],[3,1,1],[2,2,1],[2,1,1,1],[1,1,1,1,1]]
接下来计算每个子集合的积(product),并去重、排序,于是得到:
prod(5) -> [1,2,3,4,5,6]
接下来就是求这个数组中的极差、平均数和中位数了
我的方法比较“暴力”,就是先把所有的集合都先求出来,合并到一个set里面,也就是先得到prod集合,接下来按部就班即可。
过程中遇到的难点主要有两个:DFS和保留两位小数
先说后一个,平时保留的时候都是在输出的时候,即
cout<<setprecision(2)<<number;
但还没遇到说将结果保留小数放进string里面的,后来是用到了以前C里面的一个函数sprintf解决,不知道有没有其它办法(后来看了别人的solution还可以用ostringstream方法)
至于DFS,这个其实很好理解,比什么走迷宫简单多了,最开始的时候是得到1+1+1+···+1这个式子,然后1+1+···+2,直到只有n为止
贴出完整pass的代码:
#include <set>
int n, total;
int res[100000];
int times;
std::set<long long> s;
long long sum;
class IntPart
{
public:
static void dfs(int index, int n)
{
if (total == n)
{
long long num = 1;
for (int i = 0; i < times; ++i)
num *= res[i];
s.insert(num);
return;
}
if (total > n) return;
for (int i = index; i <= n; ++i)
{
total += i;
res[times++] = i;
dfs(i, n);
total -= i;
res[times--] = 0;
}
}
static std::string part(long long n)
{
sum = 0;
s.clear();
memset(res, 0, sizeof(int));
times = 0;
total = 0;
dfs(1, n);
int size1 = s.size(), pos = 0, size2;
long long med1, med2;
if (size1 % 2) size1 = size2 = size1 / 2;
else
{
size1 = size1 / 2, size2 = size1 - 1;
}
int low, high;
std::set<long long>::iterator it = s.begin();
for (; it != s.end(); ++it, ++pos)
{
sum+=(*it);
if (pos == 0) low = (*it);
if (pos + 1 == s.size()) high = (*it);
if (pos == size1) med1 = (*it);
if (pos == size2) med2 = (*it);
}
std::string ans = "Range: " + std::to_string(high - low) + " Average: ";
std::string sAve, sMed;
char cc[10] = {0};
float Ave = sum*1.0 / pos;
std::sprintf(cc, "%.2f", Ave);
sAve = cc;
float Med = (med1 + med2)*1.0 / 2;
std::sprintf(cc, "%.2f", Med);
sMed = cc;
ans = ans + sAve + " Median: " + sMed;
return ans;
}
};