Here is my code:
class Solution {
std::unordered_map<int, int> um;
public:
int coinChange(vector<int>& coins, int amount) {
if (amount == 0)
return 0;
auto it = um.find(amount);
if (it != um.end())
return it->second;
int ret = -1;
for (int c : coins)
{
int n = 1;
while (true)
{
int a = amount - n * c, m = 0;
if (a < 0)
break;
if (a > 0)
m = coinChange(coins, a);
if (m != -1)
{
if (ret == -1)
ret = m + n;
else
ret = std::min(ret, m + n);
}
n++;
}
}
um[amount] = ret;
return ret;
}
};
As far as I can tell, it is very similar to the most upvoted solution, it even constructs the same hashtable. However I get timeout at arbitrary inputs.
I am not able to find any errors locally.
Any ideas what could be wrong?
Edit:
I include the problem statement:
You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
Example:
coins = [1, 2, 5], amount = 11
return 3 (11 = 5 + 5 + 1)
The approach:
Use dynamic programming (recursion + memoization). For an amount, try every coin as long as the amount is positive. For the above example:
S(11) = 1 + S(10) | 2 + S(9) | 3 + S(8) | ... | 11 + S(0) | //try coin 1
1 + S(9) | 2 + S(7) | 3 + S(5) | ... | 5 + S(1) | //try coin 2
1 + S(6) | 2 + S(1) //try coin 5
Pardon the confusion around this question, I believe my implementation of the above idea has some bug but I have a difficult time finding it.
Later edit: I was wrong
I noticed that the running times were still too high for the C version, so that was not the issue. I managed to get all the tests from Leetcode and found the problem.
For the test case coins: {3, 7, 405, 436} and amount: 8839 my implementation would make 18744855 calls while the most popular only 34486.
This is because, for each coin, I try to put it into amount as many times as it is possible (the while (true) loop), and after each try I make a recursive call. It goes like this (for coins = {1} and amount = 3):
S(3) = min{1 + S(2), 2 + S(1), 3 + S(0)}
S(2) = min{1 + S(1), 2 + S(0)}
S(1) = min{1 + S(0)}
S(0) = 0
However it is sufficient to try the coin only once and let the recursive call handle the rest, like the popular solution does:
S(3) = min{1 + S(2)}
S(2) = min{1 + S(1)}
S(1) = min{1 + S(0)}
S(0) = 0
Previous answer:
I have ported the same exact solution to C, and that got accepted, so I assume it is some problem in the Leetcode infrastructure.
int coinChange_(int* coins, int coinsSize, int *um, int amount) {
if (amount == 0)
return 0;
if (um[amount] != 0)
return um[amount];
int ret = -1;
for (int i = 0; i < coinsSize; i++)
{
int c = coins[i];
int n = 1;
while (true)
{
int a = amount - n * c, m = 0;
if (a < 0)
break;
if (a > 0)
m = coinChange_(coins, coinsSize, um, a);
if (m != -1)
{
if (ret == -1)
ret = m + n;
else
ret = m + n < ret ? m + n : ret;
}
n++;
}
}
um[amount] = ret;
return ret;
}
int coinChange(int* coins, int coinsSize, int amount) {
int *um = calloc(amount + 1, sizeof *um);
int ret = coinChange_(coins, coinsSize, um, amount);
free(um);
return ret;
}
Related
I have a class, call it 'BigNumber', which has a vector v field.
Each element should be one digit.
I want to implement a method to multiply this vector by an integer, but also keep elements one digit.
E.g: <7,6> * 50 = <3,8,0,0>
The vector represents a number, stored in this way. In my example, <7,6> is equal to 76, and <3,8,0,0> is 3800.
I tried the following, but this isn't good (however it works), and not the actual solution for the problem.
//int num, BigNumber bn
if (num > 0)
{
int value = 0, curr = 1;
for (int i = bn.getBigNumber().size() - 1; i >= 0; i--)
{
value += bn.getBigNumber().at(i) * num * curr;
curr *= 10;
}
bn.setBigNumber(value); //this shouldn't be here
return bn;
}
The expected algortithm is multiply the vector itself, not with a variable what I convert to this BigNumber.
The way I set Integer to BigNumber:
void BigNumber::setBigNumber(int num)
{
if (num > 0)
{
bigNum.clear();
while (num != 0)
{
bigNum.push_back(num % 10);
num = (num - (num % 10)) / 10;
}
std::reverse(bigNum.begin(), bigNum.end());
}
else
{
throw TOOSMALL;
}
};
The method I want to implement:
//class BigNumber{private: vector<int> bigNum; ... }
void BigNumber::multiplyBigNumber(BigNumber bn, int num)
{
if (num > 0)
{
//bn.bigNum * num
}
else
{
throw TOOSMALL;
}
}
As this is for a school project, I don't want to just write the code for you. So here's a hint.
Let's say you give me the number 1234 --- and I choose to store each digit in a vector in reverse. So now I've got bignum = [4, 3, 2, 1].
Now you ask me to multiply that by 5. So I create a new, empty vector result=[ ]. I look at the first item in bignum. It's a 4.
4 * 5 is 20, or (as you do at school) it is 0 carry 2. So I push the 0 into result, giving result = [0] and carry = 2.
Questions for you:
If you were doing this by hand (on paper), what would you do next?
Why did I decide to store the digits in reverse order?
Why did I decide to use a new vector (result), rather than modifying bignum?
and only after you have a worked out how to multiply a bignum by an int:
How would you multiply two bignums together?
The solutin for the problem is the follow code. I don't know if I can make this algorithm faster, but it works, so I'm happy with it.
BigNumber BigNumber::multiplyBigNumber(BigNumber bn, int num){
if (num > 0)
{
std::vector<int> result;
std::vector<int> rev = bn.getBigNumber();
std::reverse(rev.begin(),rev.end());
int carry = 0;
for(int i = 0; i<rev.size(); i++){
result.push_back((rev[i] * num + carry) % 10);
carry = (rev[i] * num + carry) / 10;
if(i == rev.size()-1 && carry / 10 == 0 && carry % 10 != 0 ) {
result.push_back(carry);
carry = carry / 10;
}
}
while((carry / 10) != 0){
result.push_back(carry % 10);
carry /= 10;
if(carry / 10 == 0) result.push_back(carry);
}
std::reverse(result.begin(),result.end());
bn.setBigNumber(result);
return bn;
}else{
throw TOOSMALL;
}
}
I want to compute the number of times fib(n) is called FOR EACH n. I have written the code as below:
#include <stdio.h>
#define N 10
int count[N + 1]; // count[n] keeps track of the number of times each fib(n) is called
int fib(int n) {
count[n]++;
if(n <= 1)
return n;
else
return fib(n - 1) + fib(n - 2);
}
int main() {
for(int i = 0; i <= N; i++) {
count[i] = 0; // initialize count to 0
}
fib(N);
// print values of count[]
for(int i = 0; i <= N; i++) {
printf("count[%d] = %d", i, count[i]);
}
}
I have tried printing the array count[] to get the result, where the result is resembles the fibonacci numbers except for count[0]:
count[0] = 34 count[1] = 55 count[2] = 34 count[3] = 21 count[4] = 13
count[5] = 8 count[6] = 5 count[7] = 3 count[8] = 2 count[9] = 1
count[10] = 1
Is there a way to mathematically show this result, maybe a recursive formula? Also, why doesn't count[0], or rather fib(0), doesn't continue the fibonacci sequence? Thanks.
Because count[1] is going to be called for each count[2] + count[3] but count[0] is only going to be called for count[2]...count[1] doesn't contribute because it's a terminus.
As for mathematical formula:
if n == 0: fib(N - 1)
else: fib(N-(n-1))
As for calculation
call(n)=call(n-1)+call(n-2)+1
call(1)=1
call(0)=1
Hope this make things clear.
n | calls
---+--------
0 | 1
1 | 1
2 | 3
3 | 5 f(3)= f(2)[= f(1)+ f(0)]+ f(1)
5 | 9
.
fib(n) 2*fib(n)-1
Given a natural number n (1 <= n <= 500000), please output the summation of all its proper divisors.
Definition: A proper divisor of a natural number is the divisor that is strictly less than the number.
e.g. number 20 has 5 proper divisors: 1, 2, 4, 5, 10, and the divisor summation is: 1 + 2 + 4 + 5 + 10 = 22.
<<--This is a challenge i am trying to do and i am using recursion
int find_sum(std::vector <int> nums,long int sum,int num_now,long int j)
{
if(j<nums[num_now])
{
if(nums[num_now]%j==0)
{
sum=sum+j;
}
return find_sum(nums,sum,num_now,j+1);
}
else
{
return sum;
}
}
sum is the sum of all divisors,nums is the vector i stored number in,num_now is current member in vector,int j is 1 i use it to search for dividers,sadly using this i cant use numbers like 500000 it give's me error,is there any better way to do it or have i made a mistake somewhere.
--Thank you for your time
Here is a recursive way to solve your problem:
int find_sum(int x, int i)
{
if(i == 0)
return 0;
if(x % i == 0)
return i + find_sum(x, (i-1));
return find_sum(x, (i-1));
}
You need to call find_sum(N, N-1); in order to find sum of dividers of N (i must be less than given N because of strict inequality).
In your case it would be find_sum(20, 19);
e.g. my function returns:
71086 for N = 50000
22 for N = 20
0 for N = 1
I don't see the reason why you need to use recursion for solving this problem. I would prefer a more staightforward way to solve it.
long CalculateSumOfDivisors(int number)
{
long sum = 0;
for(int i=1; i<number; i++)
{
// If the remainder of num/i is zero
// then i divides num. So we add it to the
// current sum.
if(number%i==0)
{
sum+=i;
}
}
return sum;
}
Furthermore, we could write a more optimal algorithm, if we note the following:
Let that we have a number n and d is the smallest divisor of n that is greater of 1. (Apparently if the number n is a prime number there is any such a divisor). Then the larget divisor of n is the number n/d.
Based on this we can formulate a more optimal algorithm.
long CalculateSumOfDivisors(int number)
{
int smallestDivisor = FindSmallestDivisor(number);
if(smallestDivisor==1) return 1;
long sum = smallestDivisor;
// Calculate the possible greatest divisor.
int possibleGreatestDivisor = (int)floor(number/smallestDivisor);
for(int i=smallestDivisor+1; i<=possibleGreatestDivisor; i++)
{
if(number%i==0)
{
sum+=i;
}
}
return sum;
}
int FindSmallestDivisor(int number)
{
int smallestDivisor = 1;
for(int i=2; i<number; i++)
{
if(number%i==0)
{
smallestDivisor = i;
break;
}
}
return smallestDivisor;
}
I tried writing code with main function asking user to give the it wants to get sum of. here is the code , hope it helps.
#include<iostream>
using namespace std;
int Sum(int min, int max, int &val, int &sum){
if(min >= max)
return 0;
for ( ; min < max; min++){
if ( val%min == 0){
sum += min + val/min;
return Sum(++min,val/min, val,sum);
}
}
return 0;
}
int main(){
int s=1;
int val;
cout <<"Enter Val to sum:";
cin >> val;
Sum(2,val,val,s);
cout <<"Sum is :"<<s<<endl;
return 0;
}
Here Sum function is used recursively and passed parameters as shown in the code.
Hope it helps.
I don't think you should use recursion.
Instead start by looping from 1..N-1
When you find a divisor adjust the end value for the loop. Example if 2 is a divisor then you know N/2 is also a divisor. And just as important you know there can be no further divisors in the range ]N/2:N[. Likewise if 3 is a divisor then you know N/3 is also a divisor and you know there are no more divisors in the range ]N/3:N[.
Following that concept you can reduced the number of loops significantly for most numbers.
Something like:
long find_sum(int num)
{
long sum = 0;
int max = num;
int i = 1;
while(i < max)
{
if(num % i == 0)
{
sum += i; // Add i to the sum
max = num / i; // Decrement max for performance
if (max != i && max != num)
{
sum += max; // Add max when max isn't equal i
}
}
i++;
}
return sum;
}
Example:
num = 10
sum = 0
i = 1 -> sum = 1, max = 10
i = 2 -> sum = 1+2+5, max = 5
i = 3 -> sum = 1+2+5, max = 5
i = 4 -> sum = 1+2+5, max = 5
i = 5 -> return 8 (1+2+5)
num = 64
sum = 0
i = 1 -> sum = 1, max = 64
i = 2 -> sum = 1+2+32, max = 32
i = 3 -> sum = 1+2+32, max = 32
i = 4 -> sum = 1+2+32+4+16, max = 16
i = 5 -> sum = 1+2+32+4+16, max = 16
i = 6 -> sum = 1+2+32+4+16, max = 16
i = 7 -> sum = 1+2+32+4+16, max = 16
i = 8 -> sum = 1+2+32+4+16+8, max = 8
i = 9 -> return (1+2+32+4+16+8)
The number of loops are kept down by changing max whenever a new divisor is found.
Euler published the remarkable quadratic formula:
n² + n + 41
It turns out that the formula will produce 40 primes for the consecutive
values n = 0 to 39. However, when n =
40, 40^(2) + 40 + 41 = 40(40 + 1) + 41
is divisible by 41, and certainly when
n = 41, 41² + 41 + 41 is clearly
divisible by 41.
Using computers, the incredible formula n² − 79n + 1601 was
discovered, which produces 80 primes
for the consecutive values n = 0 to
79. The product of the coefficients, −79 and 1601, is −126479.
Considering quadratics of the form:
n² + an + b, where |a| < 1000 and |b| < 1000
where |n| is the modulus/absolute value of n
e.g. |11| = 11 and |−4| = 4
Find the product of the coefficients, a and b, for the
quadratic expression that produces the
maximum number of primes for
consecutive values of n, starting with
n = 0.
This is the problem for Euler 27.
I have attempted a solution for trying to find the equation n^2 + n + 41 to see if my logic is correct then I will attempt to see if it works on the actual problem. Here is my code (I will place comments explaining the whole program also, I would start reading from the int main function first) just make sure to read the comments so you can understand my logic:
#include <iostream>
using namespace std;
bool isPrime(int c) {
int test;
//Eliminate with some simple primes to start off with to increase speed...
if (c == 2) {
return true;
}
if (c == 3) {
return true;
}
if (c == 5) {
return true;
}
//Actual elimination starts here.
if (c <= 1 || c % 2 == 0 || c % 3 == 0 || c % 5 == 0) {
return false;
}
//Then using brute force test if c is divisible by anything lower than it except 1
//only if it gets past the first round of elimination, and if it doesn't
//pass this round return false.
for (test = c; test > 1; test--) {
if (c % test == 0) {
return false;
}
}
//If the c pasts all these tests it should be prime, therefore return true.
return true;
}
int main (int argc, char * const argv[]) {
//a as in n^2 + "a"n + b
int a = 0;
//b as in n^2 + an + "b"
int b = 0;
//n as in "n"^2 + a"n" + b
int n = 0;
//this will hold the result of n^2 + an + b so if n = 1 a = 1
//and b = 1 then c = 1^2 + 1(1) + 1 = 3
int c = 0;
//bestChain: This is to keep track for the longest chain of primes
//in a row found.
int bestChain = 0;
//chain: the current amount of primes in a row.
int chain = 0;
//bestAB: Will hold the value for the two numbers a and b that
// give the most consecutive primes.
int bestAB[2] = { 0 };
//Check every value of a in this loop
for (a = 0; a < 40; a++) {
//Check every value of b in this loop.
for (b = 0; b < 42; b++) {
//Give c a starting value
c = n*n + a*n + b;
//(1)Check if it is prime. And keep checking until it is not
//and keep incrementing n and the chain. (2)If it not prime then che
//ck if chain is the highest chain and assign the bestChain
// to the current chain. (3)Either way reset the values
// of n and chain.
//(1)
while (isPrime(c) == true) {
n++;
c = n*n + a*n + b;
chain++;
}
//(2)
if (bestChain < chain) {
bestChain = chain;
bestAB[0] = a;
bestAB[1] = b;
chain = 0;
n = 0;
}
//(3)
else {
n = 0;
chain = 0;
}
}
}
//Lastly print out the best values of a and b.
cout << bestAB[0] << " " << bestAB[1];
return 0;
}
But, I get the results 0 and 2 for a and b respectively, why is this so? Where am I going wrong? If it is still unclear just ask for more clarification on a specific area.
Your isprime method is inefficient -- but also wrong:
for (test = c; test > 1; test--) {
if (c % test == 0) {
return false;
}
}
in the first iteration of the for loop, test = c, so c % test is just c % c, which will always be 0. So your isprime method claims everything is non-prime (other than 2, 3, 5)
for (test = c; test > 1; test--) {
if (c % test == 0) {
return false;
}
}
Do you see the problem with that? If not, try working out some small sample values by hand.
As pointed out by others, your problem is in the isPrime method (test = c, so test % c = c % c == 0 is always true).
You can make your isPrime function run in O(sqrt(n)) instead of O(n) by initializing test to sqrt(c) (and only checking odd numbers). It is easy to see that if a number A is divisible by B < sqrt(A), then C = A/B must be > sqrt(A). Thus if there are no divisors < sqrt(A), there will be no divisors > sqrt(A).
Of course, you can run it a whole lot faster even, by using a probabilistic primality test, e.g. Miller-Rabin's primality test.
Also, I'm not sure, but I suspect you might reach the limit of int fairly quickly. It's probably a better idea to use unsigned long long from the start, before you start getting strange errors due to overflow & wrapping.
The sequence of triangle numbers is
generated by adding the natural
numbers. So the 7th triangle number
would be 1 + 2 + 3 + 4 + 5 + 6 + 7 =
28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55,
...
Let us list the factors of the first
seven triangle numbers:
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first
triangle number to have over five
divisors.
Given an integer n, display the first
triangle number having at least n
divisors.
Sample Input: 5
Output 28
Input Constraints: 1<=n<=320
I was obviously able to do this question, but I used a naive algorithm:
Get n.
Find triangle numbers and check their number of factors using the mod operator.
But the challenge was to show the output within 4 seconds of input. On high inputs like 190 and above it took almost 15-16 seconds. Then I tried to put the triangle numbers and their number of factors in a 2d array first and then get the input from the user and search the array. But somehow I couldn't do it: I got a lot of processor faults. Please try doing it with this method and paste the code. Or if there are any better ways, please tell me.
Here's a hint:
The number of divisors according to the Divisor function is the product of the power of each prime factor plus 1. For example, let's consider the exponential prime representation of 28:
28 = 22 * 30 * 50 * 71 * 110...
The product of each exponent plus one is: (2+1)*(0+1)*(0+1)*(1+1)*(0+1)... = 6, and sure enough, 28 has 6 divisors.
Now, consider that the nth triangular number can be computed in closed form as n(n+1)/2. We can multiply numbers written in the exponential prime form simply by adding up the exponents at each position. Dividing by two just means decrementing the exponent on the two's place.
Do you see where I'm going with this?
Well, you don't go into a lot of detail about what you did, but I can give you an optimization that can be used, if you didn't think of it...
If you're using the straightforward method of trying to find factors of a number n, by using the mod operator, you don't need to check all the numbers < n. That obviously would take n comparisons...you can just go up to floor(sqrt(n)). For each factor you find, just divide n by that number, and you'll get the conjugate value, and not need to find it manually.
For example: say n is 15.
We loop, and try 1 first. Yep, the mod checks out, so it's a factor. We divide n by the factor to get the conjugate value, so we do (15 / 1) = 15...so 15 is a factor.
We try 2 next. Nope. Then 3. Yep, which also gives us (15 / 3) = 5.
And we're done, because 4 is > floor(sqrt(n)). Quick!
If you didn't think of it, that might be something you could leverage to improve your times...overall you go from O(n) to O(sqrt (n)) which is pretty good (though for numbers this small, constants may still weigh heavily.)
I was in a programming competition way back in school where there was some similar question with a run time limit. the team that "solved" it did as follows:
1) solve it with a brute force slow method.
2) write a program to just print out the answer (you found using the slow method), which will run sub second.
I thought this was bogus, but they won.
see Triangular numbers: a(n) = C(n+1,2) = n(n+1)/2 = 0+1+2+...+n. (Formerly M2535 N1002)
then pick the language you want implement it in, see this:
"... Python
import math
def diminishing_returns(val, scale):
if val < 0:
return -diminishing_returns(-val, scale)
mult = val / float(scale)
trinum = (math.sqrt(8.0 * mult + 1.0) - 1.0) / 2.0
return trinum * scale
..."
First, create table with two columns: Triangle_Number Count_of_Factors.
Second, derive from this a table with the same columns, but consisting only of the 320 rows of the lowest triangle number with a distinct number of factors.
Perform your speedy lookup to the second table.
If you solved the problem, you should be able to access the thread on Project Euler in which people post their (some very efficient) solutions.
If you're going to copy and paste a problem, please cite the source (unless it was your teacher who stole it); and I second Wouter van Niferick's comment.
Well, at least you got a good professor. Performance is important.
Since you have a program that can do the job, you can precalculate all of the answers for 1 .. 320.
Store them in an array, then simply subscript into the array to get the answer. That will be very fast.
Compile with care, winner of worst code of the year :D
#include <iostream>
bool isPrime( unsigned long long number ){
if( number != 2 && number % 2 == 0 )
return false;
for( int i = 3;
i < static_cast<unsigned long long>
( sqrt(static_cast<double>(number)) + 1 )
; i += 2 ){
if( number % i == 0 )
return false;
}
return true;
}
unsigned int p;
unsigned long long primes[1024];
void initPrimes(){
primes[0] = 2;
primes[1] = 3;
unsigned long long number = 5;
for( unsigned int i = 2; i < 1024; i++ ){
while( !isPrime(number) )
number += 2;
primes[i] = number;
number += 2;
}
return;
}
unsigned long long nextPrime(){
unsigned int ret = p;
p++;
return primes[ret];
}
unsigned long long numOfDivs( unsigned long long number ){
p = 0;
std::vector<unsigned long long> v;
unsigned long long prime = nextPrime(), divs = 1, i = 0;
while( number >= prime ){
i = 0;
while( number % prime == 0 ){
number /= prime;
i++;
}
if( i )
v.push_back( i );
prime = nextPrime();
}
for( unsigned n = 0; n < v.size(); n++ )
divs *= (v[n] + 1);
return divs;
}
unsigned long long nextTriNumber(){
static unsigned long long triNumber = 1, next = 2;
unsigned long long retTri = triNumber;
triNumber += next;
next++;
return retTri;
}
int main()
{
initPrimes();
unsigned long long n = nextTriNumber();
unsigned long long divs = 500;
while( numOfDivs(n) <= divs )
n = nextTriNumber();
std::cout << n;
std::cin.get();
}
def first_triangle_number_with_over_N_divisors(N):
n = 4
primes = [2, 3]
fact = [None, None, {2:1}, {3:1}]
def num_divisors (x):
num = 1
for mul in fact[x].values():
num *= (mul+1)
return num
while True:
factn = {}
for p in primes:
if p > n//2: break
r = n // p
if r * p == n:
factn = fact[r].copy()
factn[p] = factn.get(p,0) + 1
if len(factn)==0:
primes.append(n)
factn[n] = 1
fact.append(factn)
(x, y) = (n-1, n//2) if n % 2 == 0 else (n, (n-1)//2)
numdiv = num_divisors(x) * num_divisors(y)
if numdiv >= N:
print('Triangle number %d: %d divisors'
%(x*y, numdiv))
break
n += 1
>>> first_triangle_number_with_over_N_divisors(500)
Triangle number 76576500: 576 divisors
Dude here is ur code, go have a look. It calculates the first number that has divisors greater than 500.
void main() {
long long divisors = 0;
long long nat_num = 0;
long long tri_num = 0;
int tri_sqrt = 0;
while (1) {
divisors = 0;
nat_num++;
tri_num = nat_num + tri_num;
tri_sqrt = floor(sqrt((double)tri_num));
long long i = 0;
for ( i=tri_sqrt; i>=1; i--) {
long long remainder = tri_num % i;
if ( remainder == 0 && tri_num == 1 ) {
divisors++;
}
else if (remainder == 0 && tri_num != 1) {
divisors++;
divisors++;
}
}
if (divisors >100) {
cout <<"No. of divisors: "<<divisors<<endl<<tri_num<<endl;
}
if (divisors > 500)
break;
}
cout<<"Final Result: "<<tri_num<<endl;
system("pause");
}
Boojum's answer motivated me to write this little program. It seems to work well, although it does use a brute force method of computing primes. It's neat how all the natural numbers can be broken down into prime number components.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <vector>
//////////////////////////////////////////////////////////////////////////////
typedef std::vector<size_t> uint_vector;
//////////////////////////////////////////////////////////////////////////////
// add a prime number to primes[]
void
primeAdd(uint_vector& primes)
{
size_t n;
if (primes.empty())
{
primes.push_back(2);
return;
}
for (n = *(--primes.end()) + 1; ; ++n)
{
// n is even -> not prime
if ((n & 1) == 0) continue;
// look for a divisor in [2,n)
for (size_t i = 2; i < n; ++i)
{
if ((n % i) == 0) continue;
}
// found a prime
break;
}
primes.push_back(n);
}
//////////////////////////////////////////////////////////////////////////////
void
primeFactorize(size_t n, uint_vector& primes, uint_vector& f)
{
f.clear();
for (size_t i = 0; n > 1; ++i)
{
while (primes.size() <= i) primeAdd(primes);
while (f.size() <= i) f.push_back(0);
while ((n % primes[i]) == 0)
{
++f[i];
n /= primes[i];
}
}
}
//////////////////////////////////////////////////////////////////////////////
int
main(int argc, char** argv)
{
// allow specifying number of TN's to be evaluated
size_t lim = 1000;
if (argc > 1)
{
lim = atoi(argv[1]);
}
if (lim == 0) lim = 1000;
// prime numbers
uint_vector primes;
// factors of (n), (n + 1)
uint_vector* f = new uint_vector();
uint_vector* f1 = new uint_vector();
// sum vector
uint_vector sum;
// prime factorize (n)
size_t n = 1;
primeFactorize(n, primes, *f);
// iterate over triangle-numbers
for (; n <= lim; ++n)
{
// prime factorize (n + 1)
primeFactorize(n + 1, primes, *f1);
while (f->size() < f1->size()) f->push_back(0);
while (f1->size() < f->size()) f1->push_back(0);
size_t numTerms = f->size();
// compute prime factors for (n * (n + 1) / 2)
sum.clear();
size_t i;
for (i = 0; i < numTerms; ++i)
{
sum.push_back((*f)[i] + (*f1)[i]);
}
--sum[0];
size_t numFactors = 1, tn = 1;
for (i = 0; i < numTerms; ++i)
{
size_t exp = sum[i];
numFactors *= (exp + 1);
while (exp-- != 0) tn *= primes[i];
}
std::cout
<< n << ". Triangle number "
<< tn << " has " << numFactors << " factors."
<< std::endl;
// prepare for next iteration
f->clear();
uint_vector* tmp = f;
f = f1;
f1 = tmp;
}
delete f;
delete f1;
return 0;
}