I'm looking for solution to find the sum of numbers. Input will be given has n in integer and problem is to find Sum of the values of sum(1)+ sum(1+2) + sum(1+2+3) + ... + sum(1+2+..+n). I need a very optimised solution using dynamic programming or any math calculation.
int main()
{
int sum = 0;
int i = 0, n = 6;
for( i = 1; i < n; i++ )
sum = sum + findSumN( i );
printf( "%d",sum );
}
You can often find a formula for series like this by calculating the first few terms and using the results to search the On-Line Encyclopedia of Integer Sequences.
1 = 1
1 + (1+2) = 4
4 + (1+2+3) = 10
10 + (1+2+3+4) = 20
20 + (1+2+3+4+5) = 35
35 + (1+2+3+4+5+6) = 56
The sequence you're trying to calculate (1, 4, 10, 20, 35, 56, ...) is A000292, which has the following formula:
a(n) = n × (n + 1) × (n + 2) / 6
If you play with the number you can find some patterns. Starts with
sum(1 + 2 + 3 ... + N) = ((1 + N) * N) /2
Then there is a relationship between the max number and the value above, that is from 1 the difference step 1/3 everytime the max number increase by 1. So get:
(1 + ((1.0 / 3.0) * (max - 1)))
I am not good enough at math to explain why this pattern occurs. Perhaps someone can explain it in a math way.
The following is my solution, no iteration needed.
int main()
{
int min = 1;
int max = 11254;
double sum = ((min + max) * max / 2) * (1 + ((1.0 / 3.0) * (max - 1)));
printf("%.f", sum);
}
Look at the closed form of sum(n)=1+2+…+n and look up the Pascal's triangle identities. This gives immediately a very fast computation method.
As
binom(k,2) + binom(k,3) = binom(k+1,3)
binom(k,2) = binom(k+1,3) - binom(k,3)
the summation of binom(k+1,2) from k=M to N results in the sum value
binom(N+2,3)-binom(M+1,3)=(N+2)*(N+1)*N/6-(M+1)*M*(M-1)/6
= (N+1-M) * ((N+1)²+(N+1)M+M²-1)/6
Related
I want to write a program that adds all the numbers between 0 and 100 but my code does not add everything correctly. How do I add the next number to the number and then print the sum?
This is the code I have:
for(int i = 0; i <= 100; i++){
i+=i;
println(i);
}
The result of this shows 0, 2, 6, 14... and I need the sum of all the numbers 1 through 100.
The reason you are getting this odd result is that you add those numbers to i instead of having a dedicated collector.
int collector = 0;
for (int i = 0; i <= 100; i++) {
collector += i;
println(collector);
}
If you only want to print the sum once, move the println(collector) expression outside the loop.
There is also a mathematical formula to directly compute the sum of the first n numbers
Sum(1, n) = n * (n+1) / 2
In Processing:
int Sum(int n){
return n * (n + 1) / 2;
}
The formula works because the numbers 1 to N can be rearranged and added like this:
(1 + N) + (2 + N-1) + (3 + N-2) + . . . . + (N + N/2+1) = total
for N = 100:
(1 + 100) + (2 + 99) + (3 + 98) + . . . . + (50 + 51) = 5050
101 + 101 + 101 + . . . . + 101 = 5050
So, I have to make a work for college and it consists in creating an algorithm.
The algorithm must find couples of numbers which satisfy a certain condition, which is: the sum from 1 to n (exlusive) results the same as the sum from n+1 to m (inclusive).
At the final, the algorithm must give at least 15 couples.
The first couple is 6 and 8, because from 1 to n (exclusive) (6) is 1+2+3+4+5 = 15 and from n+1 to m is 8+7 = 15.
The algorithm I created is the following one:
int main() {
int count = 0;
unsigned int before = 0;
unsigned int after = 0;
unsigned int n = 1;
unsigned int m = 0;
do {
before += n - 1;
after = n + 1;
for (m = after + 1; after < before; m++) {
after += m;
}
if (before == after) {
printf("%d\t%d\n", n, (m - 1));
count++;
}
n++;
} while (count < 15);
}
This is actually OK, but some of the output are not correct, and its also crap, in terms of complexity, and since I am studying Complexity of Algorithms, it would be good to find some algorithm better than this one.
I also tried doing it in Java, but using int is not good for this problem and using long, it takes hours and hours to compute.
The numbers I have found so far:
6 and 8
35 and 49
204 and 288
1189 and 1681
6930 and 9800
40391 and 57121
The following ones may be incorrect:
100469 and 107694
115619 and 134705
121501 and 144689
740802 and 745928
1250970 and 1251592
2096128 and 2097152
2100223 and 2101246
4196352 and 8388608
18912301 and 18912497
Your results are incorrect beyond the first 6: the range of type unsigned int is insufficient to store the sums. You should use type unsigned long long for before and after.
Furthermore, your algorithm becomes very slow for large values because you recompute after from scratch for each new value of before, with a time complexity of O(N2). You can keep 2 running sums in parallel and reduce the complexity to quasi-linear.
Last but not least, there are only 12 solutions below UINT32_MAX, so type unsigned long long, which is guaranteed to have at least 64 value bits is required for n and m as well. To avoid incorrect results, overflow should be tested when updating after.
Further tests show that the sums after and before exceed 64 bits for values of m around 8589934591. A solution is to subtract 262 from both before and after when they reach 263. With this modification, the program can keep searching for larger values of n and m much beyond 32-bits.
Here is an improved version:
#include <stdio.h>
int main() {
int count = 0;
unsigned long long n = 1;
unsigned long long m = 2;
unsigned long long before = 0;
unsigned long long after = 2;
for (;;) {
if (before < after) {
before += n;
n++;
after -= n;
} else {
m++;
/* reduce values to prevent overflow */
if (after > 0x8000000000000000) {
after -= 0x4000000000000000;
before -= 0x4000000000000000;
}
after += m;
while (before > after) {
after += n;
n--;
before -= n;
}
}
if (before == after) {
printf("%llu\t%llu\n", n, m);
count++;
if (count == 15)
break;
}
}
printf("%d solutions up to %llu\n", count, m);
return 0;
}
Output (running time 30 minutes):
6 8
35 49
204 288
1189 1681
6930 9800
40391 57121
235416 332928
1372105 1940449
7997214 11309768
46611179 65918161
271669860 384199200
1583407981 2239277041
9228778026 13051463048
53789260175 76069501249
313506783024 443365544448
15 solutions up to 443365544448
Your initial brute force program as posted above generates plenty of data for you to analyze. The people in the question's comments recommended the "sum of an arithmetic series" formula instead of your repeated addition, but the fact is that it still would run slow. It's surely an improvement, but it's still not good enough if you want something usable.
Believe it or not, there are some patterns to the values of n and m, which will require some math to explain. I'll be using the functions n(i), m(i), and d(i) = m(i) - n(i) to represent the values of n, m, and the difference between them, respectively, during iteration i.
You found the first six couples:
i n(i) m(i) d(i)
== ====== ====== ======
1 6 8 2
2 35 49 14
3 204 288 84
4 1189 1681 492
5 6930 9800 2870
6 40391 57121 16730
Notice that 6+8 = 14, 35+49 = 84, 204+288 = 492, etc. It so happens that, in the general case, d(i+1) = m(i) + n(i) (e.g. d(2) = m(1) + n(1) = 6 + 8 = 14).
So now we know the following:
d(7)
= n(6) + m(6)
= 40391 + 57121
= 97512
# m(i) = n(i) + d(i)
m(7) = n(7) + 97512
Another way of looking at it since m(i) = n(i) + d(i) is d(i+1) = d(i) + 2n(i):
d(7)
= n(6) + d(6) + n(6)
= d(6) + 2n(6)
= 16730 + 2(40391)
= 97512
d(i) also happens to be useful for computing n(i+1):
n(i+1) = 2d(i+1) + n(i) + 1
n(7) = 2d(7) + n(6) + 1
= 2(97512) + 40391 + 1
= 235416
From there, it's easy to determine things:
i n(i) m(i) d(i)
== ====== ====== ======
1 6 2 8
2 35 14 49
3 204 84 288
4 1189 492 1681
5 6930 2870 9800
6 40391 16370 57121
7 235416 332928 97512
But what about a starting condition? We need a way to find 6 in the first place, and that starting case can be computed by working backward and using substitution:
n(1) = 2d(1) + n(0) + 1
6 = 2(2) + n(0) + 1
5 = 4 + n(0)
1 = n(0)
d(1) = d(0) + 2n(0)
2 = d(0) + 2(1)
2 = d(0) + 2
0 = d(0)
m(0) = n(0) + d(0)
= 1 + 0
= 1
Note that n(0) = m(0) (1 = 1), but it is not a couple. For a pair of numbers to be a couple, the numbers must not be the same.
All that's left is to compute the sum. Since the integers from 1 to n-1 (i.e. 1 to n, excluding n) form an arithmetic series and the series starts at 1, you can use the formula
n(n - 1)
S(n) = --------
2
Below is a program that uses all of this information. You'll notice I'm using a multiplication function mul in place of the multiplication operator. The function's result is used to end the loop prematurely when an unsigned overflow (i.e. wraparound) is encountered. There are probably better ways to detect the wraparound behavior, and the algorithm could be better designed, but it works.
#include <errno.h>
#include <limits.h>
#include <stdio.h>
typedef unsigned long long uval_t;
/*
* Uses a version of the "FOIL method" to multiply two numbers.
* If overflow occurs, 0 is returned, and errno is ERANGE.
* Otherwise, no overflow occurs, and the product m*n is returned.
*/
uval_t mul(uval_t m, uval_t n)
{
/*
* Shift amount is half the number of bits in uval_t.
* This allows us to work with the upper and lower halves.
* If the upper half of F is not zero, overflow occurs and zero is returned.
* If the upper half of (O+I << half_shift) + L is not zero,
* overflow occurs and zero is returned.
* Otherwise, the returned value is the mathematically accurate result of m*n.
*/
#define half_shift ((sizeof (uval_t) * CHAR_BIT) >> 1)
#define rsh(v) ((v) >> half_shift)
#define lsh(v) ((v) << half_shift)
uval_t a[2], b[2];
uval_t f, o, i, l;
a[0] = rsh(m);
a[1] = m & ~lsh(a[0]);
b[0] = rsh(n);
b[1] = n & ~lsh(b[0]);
f = a[0] * b[0];
if (f != 0)
{
errno = ERANGE;
return 0;
}
o = a[0] * b[1];
i = a[1] * b[0];
l = a[1] * b[1];
if (rsh(o+i + rsh(l)) != 0)
{
errno = ERANGE;
return 0;
}
return lsh(o+i) + l;
}
int main(void)
{
int i;
uval_t n = 1, d = 0;
uval_t sum = 0;
#define MAX 15
for (i = 1; i <= MAX; i++)
{
d += n * 2;
n += d * 2 + 1;
sum = mul(n, n - 1) / 2;
if (sum == 0)
break;
printf("%2d\t%20llu\t%20llu\t%20llu\n", i, n, n+d, sum);
}
return 0;
}
This yields 12 lines of output, the last being this one:
12 1583407981 2239277041 1253590416355544190
Of course, if you don't care about the sums, then you can just avoid computing them entirely, and you can find all 15 couples just fine without even needing to check for overflow of a 64-bit type.
To go further with the sums, you have a few options, in order of most to least recommended:
use a "bignum" library such as GNU MP, which is similar to Java's java.math.BigInteger class and which has its own printf-like function for displaying values; if you're on Linux, it may already be available
use your compiler's 128-bit type, assuming it has one available, and create your own printing function for it if necessary
create your own "big integer" type and the associated necessary addition, subtraction, multiplication, division, etc. printing functions for it; a way that allows for easy printing is that it could just be two unsigned long long values glued together with one representing the lower 19 decimal digits (i.e. the max value for it would be 999 9999 9999 9999 9999), and the other representing the upper 19 digits for a total of 38 digits, which is 1038-1 or 127 bits
The fact that the full 15 sums required don't fit in 64 bits, however, makes me concerned that the question was perhaps worded badly and wanted something different from what you wrote.
Edit
To prove this works, we must first establish some rules:
For any values n and m, 0 ≤ n < m must be true, meaning n == m is forbidden (else we don't have a couple, a.k.a. "ordered pair").
n and m must both be integers.
With that out of the way, consider an algorithm for computing the sum of an arithmetic series starting at a and ending at, and including, b with a difference of +1 between each successive term:
(b - a + 1)(b + a)
S(a, b) = ------------------
2
b² - a² + b + a
= ---------------
2
b(1 + b) + a(1 - a)
= -------------------
2
If such a series begins at a=1, you can derive a simpler formula:
b(b + 1)
S(b) = --------
2
Applying this to your problem, you want to know how to find values such that the following is true:
S(n-1) = S(n+1, m)
After applying the arguments, the result looks like this:
(n-1)n m(1 + m) + (n+1)[1 - (n+1)]
------ = ---------------------------
2 2
(n-1)n = m(1 + m) + (n+1)(1 - n - 1)
n² - n = m² + m + (n+1)(-n)
n² - n = m² + m - n² - n
2n² = m² + m
While not important for my purposes, it's perhaps worth noting that m² + m can be rewritten as m(m+1), and the 2n² signifies that one or both of m and m+1 must be divisible by 2. In addition, one must be a perfect square while the other must be twice a perfect square due to the requirement that at least one expression must be divisible by 2. In other words, 2n² = m(m+1) = 2x²y². You can find another equally valid solution using x and y to generate the values of n and m, but I won't demonstrate that here.
Given the equations for n(i+1), m(i+1), and d(i+1):
d(i+1) = d(i) + 2n(i)
= m(i) + n(i)
n(i+1) = 2d(i+1) + n(i) + 1
= 2m(i) + 3n(i) + 1
m(i+1) = d(i+1) + n(i+1)
= 3m(i) + 4n(i) + 1
And the starting conditions:
n(0) = 1
d(0) = 0
m(0) = 1
We can determine whether they actually work by substituting i+2 in place of i in all cases and finding whether we end up with the same equation. Assuming f(n(i)) = 2n²(i) and g(m(i)) = m(i) ⋅ (m(i) + 1), the equation f(n(i+2)) = g(m(i+2)) reduces to f(n(i)) = g(m(i)), proving the equations work for any couple:
f(n(i+2))
= g(m(i+2))
f(2m(i+1) + 3n(i+1) + 1)
= g((3m(i+1) + 4n(i+1) + 1))
2 ⋅ (12m(i) + 17n(i) + 6)²
= (17m(i) + 24n(i) + 8) ⋅ (17m(i) + 24n(i) + 8 + 1)
2 ⋅ (144m²(i) + 408m(i)⋅n(i) + 144m(i) + 289n²(i) + 204n(i) + 36)
= 289m²(i) + 816m(i)⋅n(i) + 289m(i) + 576n²(i) + 408n(i) + 72
288m²(i) + 816m(i)⋅n(i) + 288m(i) + 578n²(i) + 408n(i) + 72
= 289m²(i) + 816m(i)⋅n(i) + 289m(i) + 576n²(i) + 408n(i) + 72
2n²(i)
= m²(i) + m(i)
f(n(i))
= g(m(i))
If you're lost toward the end, I simply subtracted 288m²(i) + 816m(i)⋅n(i) + 288m(i) + 576n²(i) + 408n(i) + 72 from both sides of the equation, yielding 2n²(i) = m²(i) + m(i).
I need help with this dynamic programming problem.
Given a positive integer k, find the maximum number of distinct positive integers that sum to k. For example, 6 = 1 + 2 + 3 so the answer would be 3, as opposed to 5 + 1 or 4 + 2 which would be 2.
The first thing I think of is that I have to find a subproblem. So to find the max sum for k, we need to find the max sum for the values less than k. So we have to iterate through the values 1 -> k and find the max sum for those values.
What confuses me is how to make a formula. We can define M(j) as the maximum number of distinct values that sum to j, but how do I actually write the formula for it?
Is my logic for what I have so far correct, and can someone explain how to work through this step by step?
No dynamic programming is need. Let's start with an example:
50 = 50
50 = 1 + 49
50 = 1 + 2 + 47 (three numbers)
50 = 1 + 2 + 3 + 44 (four numbers)
50 = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 14 (nine numbers)
Nine numbers is as far as we can go. If we use ten numbers, the sum would be at least 1 + 2 + 3 + ... + 10 = 55, which is greater than 50 - thus it is impossible.
Indeed, if we use exactly n distinct positive integers, then the lowest number with such a sum is 1+2+...+n = n(n+1)/2. By solving the quadratic, we have that M(k) is approximately sqrt(2k).
Thus the algorithm is to take the number k, subtract 1, 2, 3, etc. until we can't anymore, then decrement by 1. Algorithm in C:
int M(int k) {
int i;
for (i = 1; ; i++) {
if (k < i) return i - 1;
else k -= i;
}
}
The other answers correctly deduce that the problem essentially is this summation:
However this can actually be simplified to
In code this looks like : floor(sqrt(2.0 * k + 1.0/4) - 1.0/2)
The disadvantage of this answer is that it requires you to deal with floating point numbers.
Brian M. Scott (https://math.stackexchange.com/users/12042/brian-m-scott), Given a positive integer, find the maximum distinct positive integers that can form its sum, URL (version: 2012-03-22): https://math.stackexchange.com/q/123128
The smallest number that can be represented as the sum of i distinct positive integers is 1 + 2 + 3 + ... + i = i(i+1)/2, otherwise known as the i'th triangular number, T[i].
Let i be such that T[i] is the largest triangular number less than or equal to your k.
Then we can represent k as the sum of i different positive integers:
1 + 2 + 3 + ... + (i-1) + (i + k - T[i])
Note that the last term is greater than or equal to i (and therefore different from the other integers), since k >= T[i].
Also, it's not possible to represent k as the sum of i+1 different positive integers, since the smallest number that's the sum of i+1 different positive integers is T[i+1] > k because of how we chose i.
So your question is equivalent to finding the largest i such that T[i] <= k.
That's solved by this:
i = floor((-1 + sqrt(1 + 8k)) / 2)
[derivation here: https://math.stackexchange.com/questions/1417579/largest-triangular-number-less-than-a-given-natural-number ]
You could also write a simple program to iterate through triangular numbers until you find the first larger than k:
def uniq_sum_count(k):
i = 1
while i * (i+1) <= k * 2:
i += 1
return i - 1
for k in xrange(20):
print k, uniq_sum_count(k)
I think you just check if 1 + ... + n > k. If so, print n-1.
Because if you find the smallest n as 1 + ... + n > k, then 1 + ... + (n-1) <= k. so add the extra value, say E, to (n-1), then 1 + ... + (n-1+E) = k.
Hence n-1 is the maximum.
Note that : 1 + ... + n = n(n+1) / 2
#include <stdio.h>
int main()
{
int k, n;
printf(">> ");
scanf("%d", &k);
for (n = 1; ; n++)
if (n * (n + 1) / 2 > k)
break;
printf("the maximum: %d\n", n-1);
}
Or you can make M(j).
int M(int j)
{
int n;
for (n = 1; ; n++)
if (n * (n + 1) / 2 > j)
return n-1; // return the maximum.
}
Well the problem might be solved without dynamic programming however i tried to look at it in dynamic programming way.
Tip: when you wanna solve a dynamic programming problem you should see when situation is "repetitive". Here, since from the viewpoint of the number k it does not matter if, for example, I subtract 1 first and then 3 or first 3 and then 1; I say that "let's subtract from it in ascending order".
Now, what is repeated? Ok, the idea is that I want to start with number k and subtract it from distinct elements until I get to zero. So, if I reach to a situation where the remaining number and the last distinct number that I have used are the same the situation is "repeated":
#include <stdio.h>
bool marked[][];
int memo[][];
int rec(int rem, int last_distinct){
if(marked[rem][last_distinct] == true) return memo[rem][last_distinct]; //don't compute it again
if(rem == 0) return 0; //success
if(rem > 0 && last > rem - 1) return -100000000000; //failure (minus infinity)
int ans = 0;
for(i = last_distinct + 1; i <= rem; i++){
int res = 1 + rec(rem - i, i); // I've just used one more distinct number
if(res > ans) ans = res;
}
marked[rem][last_distinct] = true;
memo[rem][last_distinct] = res;
return res;
}
int main(){
cout << rec(k, 0) << endl;
return 0;
}
The time complexity is O(k^3)
Though it isn't entirely clear what constraints there may be on how you arrive at your largest discrete series of numbers, but if you are able, passing a simple array to hold the discrete numbers, and keeping a running sum in your functions can simplify the process. For example, passing the array a long with your current j to the function and returning the number of elements that make up the sum within the array can be done with something like this:
int largest_discrete_sum (int *a, int j)
{
int n, sum = 0;
for (n = 1;; n++) {
a[n-1] = n, sum += n;
if (n * (n + 1) / 2 > j)
break;
}
a[sum - j - 1] = 0; /* zero the index holding excess */
return n;
}
Putting it together in a short test program would look like:
#include <stdio.h>
int largest_discrete_sum(int *a, int j);
int main (void) {
int i, idx = 0, v = 50;
int a[v];
idx = largest_discrete_sum (a, v);
printf ("\n largest_discrete_sum '%d'\n\n", v);
for (i = 0; i < idx; i++)
if (a[i])
printf (!i ? " %2d" : " +%2d", a[i]);
printf (" = %d\n\n", v);
return 0;
}
int largest_discrete_sum (int *a, int j)
{
int n, sum = 0;
for (n = 1;; n++) {
a[n-1] = n, sum += n;
if (n * (n + 1) / 2 > j)
break;
}
a[sum - j - 1] = 0; /* zero the index holding excess */
return n;
}
Example Use/Output
$ ./bin/largest_discrete_sum
largest_discrete_sum '50'
1 + 2 + 3 + 4 + 6 + 7 + 8 + 9 +10 = 50
I apologize if I missed a constraint on the discrete values selection somewhere, but approaching in this manner you are guaranteed to obtain the largest number of discrete values that will equal your sum. Let me know if you have any questions.
I really need some help at this problem:
Given a positive integer N, we define xsum(N) as sum's sum of all positive integer divisors' numbers less or equal to N.
For example: xsum(6) = 1 + (1 + 2) + (1 + 3) + (1 + 2 + 4) + (1 + 5) + (1 + 2 + 3 + 6) = 33.
(xsum - sum of divizors of 1 + sum of divizors of 2 + ... + sum of div of 6)
Given a positive integer K, you are asked to find the lowest N that satisfies the condition: xsum(N) >= K
K is a nonzero natural number that has at most 14 digits
time limit : 0.2 sec
Obviously, the brute force will fall for most cases with Time Limit Exceeded. I haven't find something better than it yet, so that's the code:
fscanf(fi,"%lld",&k);
i=2;
sum=1;
while(sum<k) {
sum=sum+i+1;
d=2;
while(d*d<=i) {
if(i%d==0 && d*d!=i)
sum=sum+d+i/d;
else
if(d*d==i)
sum+=d;
d++;
}
i++;
}
Any better ideas?
For each number n in range [1 , N] the following applies: n is divisor of exactly roundDown(N / n) numbers in range [1 , N]. Thus for each n we add a total of n * roundDown(N / n) to the result.
int xsum(int N){
int result = 0;
for(int i = 1 ; i <= N ; i++)
result += (N / i) * i;//due to the int-division the two i don't cancel out
return result;
}
The idea behind this algorithm can aswell be used to solve the main-problem (smallest N such that xsum(N) >= K) in faster time than brute-force search.
The complete search can be further optimized using some rules we can derive from the above code: K = minN * minN (minN would be the correct result if K = 2 * 3 * ...). Using this information we have a lower-bound for starting the search.
Next step would be to search for the upper bound. Since the growth of xsum(N) is (approximately) quadratic we can use this to approximate N. This optimized guessing allows to find the searched value pretty fast.
int N(int K){
//start with the minimum-bound of N
int upperN = (int) sqrt(K);
int lowerN = upperN;
int tmpSum;
//search until xsum(upperN) reaches K
while((tmpSum = xsum(upperN)) < K){
int r = K - tmpSum;
lowerN = upperN;
upperN += (int) sqrt(r / 3) + 1;
}
//Now the we have an upper and a lower bound for searching N
//the rest of the search can be done using binary-search (i won't
//implement it here)
int N;//search for the value
return N;
}
Days ago I had a job interview were they ask me how I would calculate the sum of all the numbers multiples of 2 or 5 from 1 to 10000 using a the c language. I did this:
int mult2_5()
{
int i, sum=0;
for(i = 1; i <= 10000; i++)
if(i % 2 == 0 || i % 5 == 0)
sum += i;
return sum;
}
I as wonder if it was any faster implementation that this one?
The modulus operator is inefficient. A more faster implementation would be something like this:
int multiply2_5(int max)
{
int i, x2 = 0,x5 = 0,x10 = 0;
for(i = 2; i < max; i+=2) x2 += i; // Store all multiples of 2 O(max/2)
for(i = 5; i < max; i+=5) x5 += i; // Store all multiples of 3 O(max/5)
for(i = 10; i < max; i+=10) x10 += i; // Store all multiples 10; O(max/10)
return x2+x5-x10;
}
In this solution I had to take out multiples of 10 because, 2 and 5 have 10 as multiple so on the second loop it will add multiples of 10 that already been added in the first loop; The three loops combine have O(8/10 max).
Another even better solution is if you take a mathematical approach.
You are trying to sum all numbers like this 2 + 4 + 6 + 8 ... 10000 and 5 + 10 + 15 +20 + ... 10000 this is the same of having 2 * (1 + 2 + 3 + 4 + … + 5000) and 5 * ( 1 + 2 + 3 + 4 + ... + 2000), the sum of 'n' natural number is (n * (n + 1)) (source) so you can calculate in a constant time, as it follows:
int multiply2_5(int max)
{
// x = 2 + 4 + 6 + ... = 2 * (1 + 2 + 3 +...)
// y = 5 + 10 + 15 + ... = 5 * (1 + 2 + 3 +...)
// The sun of n natural numbers is sn = (n (n + 1)) / 2
int x2 = max/ 2; // 2 * ( 1 +2 + 3 … max/2)
int x5 = max /5; // 5 * ( 1 +2 + 3 … max/5)
int x10 = max/ 10;
int sn2 = 0.5 * (x2 * (x2+1)); // (n * (n + 1)) / 2
int sn5 = 0.5 * (x5 * (x5+1));
int sn10 = 0.5 * (x10 * (x10+1));
return (2*sn2) + (5 *sn5) - (10*sn10);
}
As mentioned in an earlier answer, explicitly looping through the relevant multiples is better than testing the remainder each loop. But it is not necessary to calculate the multiples of 10 and subtract. Just start at 5 and step by 10 to skip them all together.
int multiply2_5b(int max)
{
int i, x2 = 0,x5 = 0;
for (i = 2; i < max; i += 2) x2 += i; // Sum all multiples of 2
for (i = 5; i < max; i += 10) x5 += i; // Sum all odd multiples of 5
return x2 + x5;
}
Just work it out on paper first, if that's what you mean by "faster".
$2\sum_{1<=2k<=10000}k + 5\sum_{1<=5k<=10000} - 10\sum_{1<=10k<=10000}k$
Sorry, my SO equation-fu is weak...Anyway this route will give you something you can almost handle on paper: 5000*6001 after reducing a few steps
int
mult2_5(void)
{
return 5000*6001;
}
Project Euler problem 1 is very similar. There's lots of folks who've posted their solution to this one.
This can just be done using math. Something like 2 * sum(1 to 5000) + 5 * sum(1 to 2000) - 10 * sum(1 to 1000). off-by-one errors left as exercise.
I almost got to a pure and simple multiplication by doing a simple loop that starts with 35 (sum of 2 + 4 + 5 + 6 + 8 + 10) with a step of 60, as that's how much your result will increase by when you take the next lot e.g. 12 + 14 + 15 + 16 + 18 + 20 etc. for(int i=35;i<5976;i=i+60) { sum=sum+i }
The 5976 comes from 5975 being the last row of numbers that end in 1000 i.e. 992 + 994 + 995 + 996 + 998 + 1000.
So it turns out that this loop runs 100 times, increasing the sum by 35 the first turn and increasing by 60 the remaining 99 times. Which is now reducable to a simple multiplication or such.