Project Euler Problem 53 (C++和Python)
阿新 • • 發佈:2018-12-26
Problem 53: Combinatoric selections
There are exactly ten ways of selecting three from five, 12345:
123, 124, 125, 134, 135, 145, 234, 235, 245, and 345
In combinatorics, we use the notation, 5C3 = 10.
In general,
nCr = n! / r!(n−r)! , where r ≤ n, n! = n×(n−1)×…×3×2×1, and 0! = 1.
It is not until n = 23, that a value exceeds one-million: 23
How many, not necessarily distinct, values of nCr, for 1 ≤ n ≤ 100, are greater than one-million?
C++ source code
#include <iostream>
#include <algorithm>
#include <cassert>
using namespace std;
class PE0053
{
public:
long long getCombinationValue(int n, int r);
int findNumOfnCrGreaterThanOneMillion();
private:
static const int m_max = 1000000;
};
#ifdef UNIT_TEST
long long PE0053::getCombinationValue(int n, int r)
{
long double nCr = 1.0;
int i = n;
int j = n-r;
if (n > r) // r>=1
{
while(1)
{
if (i > r)
{
nCr *= i; // nCr = n*(n-1)...*(r+1)
i--;
}
if (j > 0)
{
nCr /=j; // nCr = (n*(n-1)...*r)/((n-r)*(n-r-1)...*1)
j--;
}
// if nCr is greater than one-million, don't continue.
if (nCr>1000000.0 || j==0 || i==r)
{
break;
}
}
}
return (long long)nCr;
}
#else
long long PE0053::getCombinationValue(int n, int r)
{
long long nCr = 1;
for(int i=0; i<min(r, n-r); i++)
{
nCr = nCr * (n-i) / (i+1);
if (nCr > m_max)
{
break;
}
}
return nCr;
}
#endif
int PE0053::findNumOfnCrGreaterThanOneMillion()
{
int numOfnCr = 0;
for(int n=23; n<=100;n++)
{
for(int r=1; r<=n/2; r++)
{
if (getCombinationValue(n, r) > m_max)
{
// count from C(n,r) to C(n,n-r),because C(n,r)=C(n,n-r) (r<=n-r)
numOfnCr += (n-r) - r + 1;
break;
}
}
}
return numOfnCr;
}
int main()
{
PE0053 pe0053;
assert (pe0053.getCombinationValue(23, 10) == 1144066);
cout << pe0053.findNumOfnCrGreaterThanOneMillion() << ", not necessarily ";
cout << "distinct, values of nCr, for 1<=n<=100, are greater ";
cout << "than one-million" << endl;
return 0;
}
Python source code
import math
def getCombinationValueOld(n, r):
"""
nCr = n!/r!(n−r)!
"""
nCr = math.factorial(n)/math.factorial(r)
nCr /= math.factorial(n-r)
return nCr
def getCombinationValue(n, r):
"""
Calculate C(n, r), the number of ways can r be chosen from n. Example:
>>>C(30,12)
86493225
"""
nCr = 1
for t in range(min(r, n-r)):
nCr = nCr * (n-t) // (t+1)
return nCr
def findNumOfnCrGreaterThanOneMillion():
"""
count all nCrs whose values are greater than one million
"""
numOfnCr = 0
for n in range(23, 101):
for r in range(2, n//2):
if getCombinationValue(n, r) > 10**6:
# count from C(n,r) to C(n,n-r), because C(n,r) = C(n,n-r)
numOfnCr += (n-r) - r + 1
break
return numOfnCr
def main():
assert getCombinationValueOld(23, 10) == 1144066
print(findNumOfnCrGreaterThanOneMillion(),", not necessarily "\
"distinct, values of nCr, for 1<=n<=100, are greater "\
"than one-million")
if __name__ == '__main__':
main()