what is the complexity of the following c Function ?
double foo (int n) {
int i;
double sum;
if (n==0) return 1.0;
else {
sum = 0.0;
for (i =0; i<n; i++)
sum +=foo(i);
return sum;
}
}
Please don't just post the complexity can you help me in understanding how to go about it .
EDIT: It was an objective question asked in an exam and the Options provided were
1.O(1)
2.O(n)
3.O(n!)
4.O(n^n)
It's Θ(2^n) ( by assuming f is a running time of algorithm we have):
f(n) = f(n-1) + f(n-2) + ... + 1
f(n-1) = f(n-2) + f(n-3) + ...
==> f(n) = 2*f(n-1), f(0) = 1
==> f(n) is in O(2^n)
Actually if we ignore the constant operations, the exact running time is 2n.
Also in the case you wrote this is an exam, both O(n!) and O(n^n) are true and nearest answer to Θ(2^n) among them is O(n!), but if I was student, I'll mark both of them :)
Explanation on O(n!):
for all n >= 1: n! = n(n-1)...*2*1 >= 2*2*2*...*2 = 2^(n-1) ==>
2 * n! >= 2^n ==> 2^n is in O(n!),
Also n! <= n^n for all n >= 1 so n! is in O(n^n)
So O(n!) in your question is nearest acceptable bound to Theta(2^n)
For one, it is poorly coded :)
double foo (int n) { // foo return a double, and takes an integer parameter
int i; // declare an integer variable i, that is used as a counter below
double sum; // this is the value that is returned
if (n==0) return 1.0; // if someone called foo(0), this function returns 1.0
else { // if n != 0
sum = 0.0; // set sum to 0
for (i =0; i<n; i++) // recursively call this function n times, then add it to the result
sum +=foo(i);
return sum; // return the result
}
}
You're calling foo() a total of something like n^n (where you round n down to the nearest integer)
e.g.:
foo(3)will be called 3^3 times.
Good luck, and merry Christmas.
EDIT: oops, just corrected something. Why does foo return a double? It will always return an integer, not a double.
Here would be a better version, with micro-optimizations! :D
int foo(int n)
{
if(n==0) return 1;
else{
int sum = 0;
for(int i = 0; i < n; ++i)
sum += foo(i);
return sum;
}
}
You could have been a bit more clearer... grumble grumble
<n = ?> : <return value> : <number of times called>
n = 0 : 1 : 1
n = 1 : 1 : 2
n = 2 : 2 : 4
n = 3 : 4 : 8
n = 4 : 8 : 16
n = 5 : 16 : 32
n = 6 : 32 : 64
n = 7 : 64 : 128
n = 8 : 128 : 256
n = 9 : 256 : 512
n = 10 : 512 : 1024
number_of_times_called = pow(2, n-1);
Let's try putting in inputs, shall we?
Using this code:
#include <iostream>
double foo (int n) {
int i;
double sum;
if (n==0) return 1.0;
else {
sum = 0.0;
for (i =0; i<n; i++)
sum +=foo(i);
return sum;
}
}
int main(int argc, char* argv[])
{
for(int n = 0; 1; n++)
{
std::cout << "n = " << n << " : " << foo(n);
std::cin.ignore();
}
return(0);
}
We get:
n = 0 : 1
n = 1 : 1
n = 2 : 2
n = 3 : 4
n = 4 : 8
n = 5 : 16
n = 6 : 32
n = 7 : 64
n = 8 : 128
n = 9 : 256
n = 10 : 512
Therefore, it can be simplified to:
double foo(int n)
{
return((double)pow(2, n));
}
The function is composed of multiple parts.
The first bit of complexity is the if(n==0)return 1.0;, since that only generates one run. That would be O(1).
The next part is the for(i=0; i<n; i++) loop. Since that loops from 0..n it is O(n)
Than there is the recursion, for every number in n you run the function again. And in that function again the loop, and the next function. And so on...
To figure out what it will be I recommend you add a global ounter inside of the loop so you can see how many times it is executed for a certain number.
Related
I am trying to construct a simple program which adds together the digits of a long number. I attempted to do this by using a loop employing the modulo operator and some basic arithmetic. I want to increment the modulo operator by multiplying it by ten on each iteration of the loop in order to reach the next digit. I want to check if my code is correct, however, I receive errors pertaining to the lines involving the modulo operations and I'm not quite sure why.
This was my attempted construction:
{
long i = 0;
long b;
int m = 1;
do
{
long number = get_long("Number?\n");
long a = number % m;
b = number - a;
long c = b % m x 10;
long d = c / m;
{
i = i + d;
}
{
m = m x 10
}
}
while (b > 0);
printf("%ld\n", i);
}
Edit:
I made the basic error of writing "x" instead of "*". However, having fixed this, I no longer receive errors, but the program simply returns "0". Any diagnosis would be appreciated.
int main(void)
{
long i = 0;
long b;
int m = 10;
long number = get_long("Number?\n");
do
{
long a = number % m;
b = number - a;
long c = b % m * 10;
long d = c / m;
{
i = i + d;
}
{
m = m * 10;
}
}
while (b > 0);
printf("%ld\n", i);
}
For your revised code:
long c = b % m * 10;
this line will evaluate (b % m) and then multiply it by 10 because of the order of operations.
I presume what you actually want is:
long c = b % (m * 10);
Secondly, the following line determines which digit you start at:
int m = 10;
and this line determines how many digits between the ones you include in your total:
m = m * 10;
So for this configuration, it will start at the 2nd digit from the right and add every digit.
So for the number 1234, you'd get 3 + 2 + 1 = 6.
If you want to add every digit, you could set:
int m = 10;
and you'd get 4 + 3 + 2 + 1 = 10.
Alternatively, if you had used:
m = m * 10;
you'd have 3 + 1 = 4.
First, you're likely getting errors due to these lines:
long c = b % m x 10;
m = m x 10
This is because x is not a valid operator.
The multiplication operator is *:
long c = b % m * 10;
m = m * 10;
As for your approach, I would suggest, instead of changing the modulo operand, you simply divide the original number by 10 to shift it one digit each operation.
For example:
#include <stdio.h>
int main()
{
int sumofdigits = 0;
int num = 12345;
while(num > 0) {
sumofdigits += num % 10;
num /= 10;
}
printf("%d", sumofdigits);
return 0;
}
The reduced-sum of the digits of a number is the same as that number modulo 9.
Example:
#include <stdio.h>
int main(void) {
int number = 57283;
printf("%d \n", number%9);
// 5 + 7 + 2 + 8 + 3 == 25 ==> 2 + 5 == 7
// 57283 % 9 == 7
return 0;
}
If you want to use loops to get the reduced sum:
int sum_of_digits(int num)
{
int sum;
do
{
sum = 0;
while(num)
{
sum += num%10;
num /= 10;
}
num = sum;
} while (sum >9);
return sum;
}
But if you only want the simple sum of digits (one pass only):
int sum_of_digits(int num)
{
int sum = 0;
while(num)
{
sum += num%10;
num /= 10;
}
return sum;
}
You have to find the sum of the digits of a variable of type long by the two operators modulo (%) and division (/), you start with the operator modulo to find the remainder of the division (the digits) then, you add this degit to the sum, then you do the division / 10 to overwrite (the summed digit) until the number is equal to 0 like this:
int main()
{
long number=0,m=0;
printf("Give a number :");
scanf("%ld",&number);
long s=0,temp=number;
while(number != 0)
{
m=number%10;
s+=m;
number/=10;
}
printf("\n%The sum of the digits of the Number %ld is : %ld\n",temp,s);
}
What will be the time complexity for the following code?
int fun1(int n) {
int i = 1;
int count = 0;
while (i < n) {
count++;
i = i * 2;
}
printf("Loop ran %d times\n", count);
return 0;
}
All sentences are O(1) and the loop does log(n) (base 2) iterations as i doubles itselves (i=i*2) every iteration, so its log(n) (base 2).
You can find more information here What is time complexity of while loops?.
The time complexity of the above code is : O(log(n))
int fun1(int n) {
int i = 1;
int count = 0;
// Here i runs from 1 to n
// but i doubles every time
// i = 1 2 4 8 16 .... n
// Hence O(log(n))
while (i < n) {
count++;
i = i * 2;
}
printf("Loop ran %d times\n", count);
return 0;
}
Suppose n = 16 == 2^4
In that case the loop will run only 4 time == 1 2 4 8 == log(16)
Look at this part of your code:
while (i < n) {
count++;
i = i * 2;
}
i is multiplied by 2 in every iteration.
Initially, i is 1.
Iteration I:
i = 1 * 2; => i = 2
Iteration II:
i = 2 * 2; => i = 4
Iteration III:
i = 4 * 2; => i = 8
Iteration IV:
i = 8 * 2; => i = 16
.....
.....
and so on..
Assuming n is a number which is equal to 2k. Which means, loop will execute k times. At kth step:
2k = n
Taking logarithms (base 2) on both side:
log(2k) = log(n)
k log(2) = log(n)
k = log(n) [as log2(base 2) = 1]
Hence, time complexity is O(log(n)).
I'm facing some difficulties in the last few days while trying to finish the following task, I hope you guys can assist :
I'm given a single number N, and I'm allowed to perform any of the two operations on N in each move :
One - If we take 2 integers where N = x * y , then we can change the value of N to the maximum between x and y.
Two - Decrease the value of N by 1.
I want to find the minimum number of steps to reduce N to zero.
This is what I have so far, I'm not sure what is the best way to implement the function to find the divisor (someFindDevisorFunction), and if this 'f' function would actually produce the required output.
int f(int n)
{
int div,firstWay,secondWay;
if(n == 0)
return 0;
div = SomefindDivisorFunction(n);
firstWay = 1 + f(n-1);
if(div != 1)
{
secondWay = 1 + f(div);
if (firstWay < secondWay)
return firstWay;
return secondWay;
}
return firstWay;
}
For example, if I enter the number 150 , the output would be :
75 - 25 - 5 - 4 - 2 - 1 - 0
I see this a recursive or iterative problem.
OP's approach hints at recursive.
A recursive solution follows:
At each step, code counts the steps of the various alternatives:
steps(n) = min(
steps(factor1_of_n) + 1,
steps(factor2_of_n) + 1,
steps(factor3_of_n) + 1,
...
steps(n-1) + 1)
The coded solution below is inefficient, but it does explore all possibilities and gets to the answer.
int solve_helper(int n, bool print) {
int best_quot = 0;
int best_quot_score = INT_MAX;
int quot;
for (int p = 2; p <= (quot = n / p); p++) {
int rem = n % p;
if (rem == 0 && quot > 1) {
int score = solve_helper(quot, false) + 1;
if (score < best_quot_score) {
best_quot_score = score;
best_quot = quot;
}
}
}
int dec_score = n > 0 ? solve_helper(n - 1, false) + 1 : 0;
if (best_quot_score < dec_score) {
if (print) {
printf("/ %d ", best_quot);
solve_helper(best_quot, true);
}
return best_quot_score;
}
if (print && n > 0) {
printf("- %d ", n - 1);
solve_helper(n - 1, true);
}
return dec_score;
}
int main() {
int n = 75;
printf("%d ", n);
solve(n, true);
printf("\n");
}
Output
75 / 25 / 5 - 4 / 2 - 1 - 0
Iterative
TBD
If you start looking for a divisor with 2, and work your way up, then the last pair of divisors you find will include the largest divisor. Alternatively you can start searching with divisor = N/2 and work down, when the first divisor found will have be largest divisor of N.
int minmoves(int n){
if(n<=3){
return n;
}
int[] dp=new int[n+1];
Arrays.fill(dp,-1);
dp[0]=0;
dp[1]=1;
dp[2]=2;
dp[3]=3;
int sqr;
for(int i=4;i<=n;i++){
sqr=(int)Math.sqrt(i);
int best=Integer.MAX_VALUE;
while(sqr >1){
if(i%sqr==0){
int fact=i/sqr;
best=Math.min(best,1+dp[fact]);
}
sqr--;
}
best=Math.min(best,1+dp[i-1]);
dp[i]=best;
}
return dp[n];
}
I have removed all the storylines for this question.
Q. You are given N numbers. You have to find 2 equal sum sub-sequences, with maximum sum. You don't necessarily need to use all numbers.
Eg 1:-
5
1 2 3 4 1
Sub-sequence 1 : 2 3 // sum = 5
Sub-sequence 2 : 4 1 // sum = 5
Possible Sub-sequences with equal sum are
{1,2} {3} // sum = 3
{1,3} {4} // sum = 4
{2,3} {4,1} // sum = 5
Out of which 5 is the maximum sum.
Eg 2:-
6
1 2 4 5 9 1
Sub-sequence 1 : 2 4 5 // sum = 11
Sub-sequence 2 : 1 9 1 // sum = 11
The maximum sum you can get is 11
Constraints:
5 <= N <= 50
1<= number <=1000
sum of all numbers is <= 1000
Important: Only <iostream> can be used. No STLs.
N numbers are unsorted.
If array is not possible to split, print 0.
Number of function stacks is limited. ie your recursive/memoization solution won't work.
Approach 1:
I tried a recursive approach something like the below:
#include <iostream>
using namespace std;
bool visited[51][1001][1001];
int arr[51];
int max_height=0;
int max_height_idx=0;
int N;
void recurse( int idx, int sum_left, int sum_right){
if(sum_left == sum_right){
if(sum_left > max_height){
max_height = sum_left;
max_height_idx = idx;
}
}
if(idx>N-1)return ;
if(visited[idx][sum_left][sum_right]) return ;
recurse( idx+1, sum_left+arr[idx], sum_right);
recurse( idx+1, sum_left , sum_right+arr[idx]);
recurse( idx+1, sum_left , sum_right);
visited[idx][sum_left][sum_right]=true;
/*
We could reduce the function calls, by check the visited condition before calling the function.
This could reduce stack allocations for function calls. For simplicity I have not checking those conditions before function calls.
Anyways, this recursive solution would get time out. No matter how you optimize it.
Btw, there are T testcases. For simplicity, removed that constraint.
*/
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cin>>N;
for(int i=0; i<N; i++)
cin>>arr[i];
recurse(0,0,0);
cout<< max_height <<"\n";
}
NOTE: Passes test-cases. But time out.
Approach 2:
I also tried, taking advantage of constraints.
Every number has 3 possible choice:
1. Be in sub-sequence 1
2. Be in sub-sequence 2
3. Be in neither of these sub-sequences
So
1. Be in sub-sequence 1 -> sum + 1*number
2. Be in sub-sequence 2 -> sum + -1*number
3. None -> sum
Maximum sum is in range -1000 to 1000.
So dp[51][2002] could be used to save the maximum positive sum achieved so far (ie till idx).
CODE:
#include <iostream>
using namespace std;
int arr[51];
int N;
int dp[51][2002];
int max3(int a, int b, int c){
return max(a,max(b,c));
}
int max4(int a, int b, int c, int d){
return max(max(a,b),max(c,d));
}
int recurse( int idx, int sum){
if(sum==0){
// should i perform anything here?
}
if(idx>N-1){
return 0;
}
if( dp[idx][sum+1000] ){
return dp[idx][sum+1000];
}
return dp[idx][sum+1000] = max3 (
arr[idx] + recurse( idx+1, sum + arr[idx]),
0 + recurse( idx+1, sum - arr[idx]),
0 + recurse( idx+1, sum )
) ;
/*
This gives me a wrong output.
4
1 3 5 4
*/
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cin>>N;
for(int i=0; i<N; i++)
cin>>arr[i];
cout<< recurse(0,0) <<"\n";
}
The above code gives me wrong answer. Kindly help me with solving/correcting this memoization.
Also open to iterative approach for the same.
Idea of your second approach is correct, it's basically a reduction to the knapsack problem. However, it looks like your code lacks clear contract: what the recurse function is supposed to do.
Here is my suggestion: int recurse(int idx, int sum) distributes elements on positions idx..n-1 into three multisets A, B, C such that sum+sum(A)-sum(B)=0 and returns maximal possible sum(A), -inf otherwise (here -inf is some hardcoded constant which serves as a "marker" of no answer; there are some restrictions on it, I suggest -inf == -1000).
Now you're to write a recursive backtracking using that contract and then add memoization. Voila—you've got a dynamic programming solution.
In recursive backtracking we have two distinct situations:
There are no more elements to distribute, no choices to make: idx == n. In that case, we should check that our condition holds (sum + sum(A) - sum(B) == 0, i.e. sum == 0) and return the answer. If sum == 0, then the answer is 0. However, if sum != 0, then there is no answer and we should return something which will never be chosen as the answer, unless there are no answer for the whole problem. As we modify returning value of recurse and do not want extra ifs, it cannot be simply zero or even -1; it should be a number which, when modified, still remains "the worst answer ever". The biggest modification we can make is to add all numbers to the resulting value, hence we should choose something less or equal to negative maximal sum of numbers (i.e. -1000), as existing answers are always strictly positive, and that fictive answer will always be non-positive.
There is at least one remaining element which should be distributed to either A, B or C. Make the choice and choose the best answer among three options. Answers are calculated recursively.
Here is my implementation:
const int MAXN = 50;
const int MAXSUM = 1000;
bool visited[MAXN + 1][2 * MAXSUM + 1]; // should be filled with false
int dp[MAXN + 1][2 * MAXSUM + 1]; // initial values do not matter
int recurse(int idx, int sum){
// Memoization.
if (visited[idx][sum + MAXSUM]) {
return dp[idx][sum + MAXSUM];
}
// Mark the current state as visited in the beginning,
// it's ok to do before actually computing it as we're
// not expect to visit it while computing.
visited[idx][sum + MAXSUM] = true;
int &answer = dp[idx][sum + MAXSUM];
// Backtracking search follows.
answer = -MAXSUM; // "Answer does not exist" marker.
if (idx == N) {
// No more choices to make.
if (sum == 0) {
answer = 0; // Answer exists.
} else {
// Do nothing, there is no answer.
}
} else {
// Option 1. Current elemnt goes to A.
answer = max(answer, arr[idx] + recurse(idx + 1, sum + arr[idx]));
// Option 2. Current element goes to B.
answer = max(answer, recurse(idx + 1, sum - arr[idx]));
// Option 3. Current element goes to C.
answer = max(answer, recurse(idx + 1, sum));
}
return answer;
}
Here is a simple dynamic programming based solution for anyone interested, based on the idea suggested by Codeforces user lemelisk here. Complete post here. I haven't tested this code completely though.
#include <iostream>
using namespace std;
#define MAXN 20 // maximum length of array
#define MAXSUM 500 // maximum sum of all elements in array
#define DIFFSIZE (2*MAXSUM + 9) // possible size of differences array (-maxsum, maxsum) + some extra
int dp[MAXN][DIFFSIZE] = { 0 };
int visited[DIFFSIZE] = { 0 }; // visited[diff] == 1 if the difference 'diff' can be reached
int offset = MAXSUM + 1; // offset so that indices in dp table don't become negative
// 'diff' replaced by 'offset + diff' below everywhere
int max(int a, int b) {
return (a > b) ? a : b;
}
int max_3(int a, int b, int c) {
return max(a, max(b, c));
}
int main() {
int a[] = { 1, 2, 3, 4, 6, 7, 5};
int n = sizeof(a) / sizeof(a[0]);
int *arr = new int[n + 1];
int sum = 0;
for (int i = 1; i <= n; i++) {
arr[i] = a[i - 1]; // 'arr' same as 'a' but with 1-indexing for simplicity
sum += arr[i];
} // 'sum' holds sum of all elements of array
for (int i = 0; i < MAXN; i++) {
for (int j = 0; j < DIFFSIZE; j++)
dp[i][j] = INT_MIN;
}
/*
dp[i][j] signifies the maximum value X that can be reached till index 'i' in array such that diff between the two sets is 'j'
In other words, the highest sum subsets reached till index 'i' have the sums {X , X + diff}
See http://codeforces.com/blog/entry/54259 for details
*/
// 1 ... i : (X, X + diff) can be reached by 1 ... i-1 : (X - a[i], X + diff)
dp[0][offset] = 0; // subset sum is 0 for null set, difference = 0 between subsets
visited[offset] = 1; // initially zero diff reached
for (int i = 1; i <= n; i++) {
for (int diff = (-1)*sum; diff <= sum; diff++) {
if (visited[offset + diff + arr[i]] || visited[offset + diff - arr[i]] || visited[offset + diff]) {
// if difference 'diff' is reachable, then only update, else no need
dp[i][offset + diff] = max_3
(
dp[i - 1][offset + diff],
dp[i - 1][offset + diff + arr[i]] + arr[i],
dp[i - 1][offset + diff - arr[i]]
);
visited[offset + diff] = 1;
}
}
/*
dp[i][diff] = max {
dp[i - 1][diff] : not taking a[i] in either subset
dp[i - 1][diff + arr[i]] + arr[i] : putting arr[i] in first set, thus reducing difference to 'diff', increasing X to X + arr[i]
dp[i - 1][diff - arr[i]] : putting arr[i] in second set
initialization: dp[0][0] = 0
*/
// O(N*SUM) algorithm
}
cout << dp[n][offset] << "\n";
return 0;
}
Output:
14
State is not updated in Approach 1. Change the last line of recurse
visited[idx][sum_left][sum_right];
to
visited[idx][sum_left][sum_right] = 1;
Also memset the visited array to false before calling recurse from main.
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.