Ranking (as of 2013-06-15): 141 out of 976
Language: C++
/*
UVa 10375 - Choose and divide
To build using Visual Studio 2008:
cl -EHsc -O2 choose_and_divide.cpp
*/
#include <iostream>
#include <utility>
#include <algorithm>
#include <limits>
#include <cstdio>
using namespace std;
/*
C(p, q) / C(r, s) = (p! * s! * (r - s)!) / (q! * r! * (p - q)!)
*/
const int nr_facts = 3; // number of factorials
bool multiply_by_partial_factorial(pair<int, int>& pfact, double result_max,
double& result)
{
int i;
for (i = pfact.first; i <= pfact.second; ) {
result *= static_cast<double>(i++);
if (result > result_max)
break;
}
pfact.first = i;
return pfact.first > pfact.second;
}
bool divide_by_partial_factorial(pair<int, int>& pfact, double result_min,
double& result)
{
int i;
for (i = pfact.first; i <= pfact.second; ) {
result /= static_cast<double>(i++);
if (result < result_min)
break;
}
pfact.first = i;
return pfact.first > pfact.second;
}
int main()
{
int p, q, r, s;
while (cin >> p >> q >> r >> s) {
int dvd_facts[nr_facts] = {p, s, r - s}, // dividend factorials
dvs_facts[nr_facts] = {q, r, p - q}; // divisor factorials
sort(dvd_facts, dvd_facts + nr_facts);
sort(dvs_facts, dvs_facts + nr_facts);
int i, j, nr_dvd_pfacts = 0, nr_dvs_pfacts = 0;
pair<int, int> dvd_pfacts[nr_facts], dvs_pfacts[nr_facts];
// dividend/divisor partial factorials
for (i = 0; i < nr_facts; i++) {
if (dvd_facts[i] > dvs_facts[i])
dvd_pfacts[nr_dvd_pfacts++] = make_pair(dvs_facts[i] + 1, dvd_facts[i]);
else if (dvd_facts[i] < dvs_facts[i])
dvs_pfacts[nr_dvs_pfacts++] = make_pair(dvd_facts[i] + 1, dvs_facts[i]);
}
i = j = 0;
double result = 1.0;
const double result_min =
numeric_limits<float>::min(), result_max = numeric_limits<float>::max();
do {
if (i < nr_dvd_pfacts &&
multiply_by_partial_factorial(dvd_pfacts[i], result_max, result))
i++;
if (j < nr_dvs_pfacts &&
divide_by_partial_factorial(dvs_pfacts[j], result_min, result))
j++;
} while (i < nr_dvd_pfacts || j < nr_dvs_pfacts);
printf("%.5lf\n", result);
}
return 0;
}
No comments:
Post a Comment