I was trying to solve the following problem:
Weighted Sum Problem
The closest problem I have done before is Kadane's algorithm, so I tried the "max ending here" approach, which led to the following DP-based program. The idea is to break the problem down into smaller identical problems (the usual DP).
#include<stdio.h>
#include<stdlib.h>
main(){
int i, n, m, C[20002], max, y, x, best, l, j;
int a[20002], b[20002];
scanf("%d %d", &n, &m);
for(i=0;i<n;i++){
scanf("%d",&C[i]);
}
a[0] = C[0];
max = C[0];
for(i=1;i<n;i++){
max = (C[i]>max) ? C[i] : max;
a[i] = max;
}
for(l=0;l<n;l++){
b[l] = 0;
}
for(y=2;y<m+1;y++){
for(x=y-1;x<n;x++){
best = max = 0;
for(j=0;j<y;j++){
max += (j+1) * C[j];
}
for(i=y-1;i<x+1;i++){
best = a[i-1] + y * C[i];
max = (best>max) ? best : max;
}
b[x] = max;
}
for(l=0;l<n;l++){
a[l] = b[l];
}
}
printf("%d\n",b[n-1]);
system("PAUSE");
return 0;
}
But this program does not work within the specified time limit (space limit is fine). Please give me a hint on the algorithm to be used on this problem.
EDIT.
Here is the explanation of the code:
Like in Kadane's, my idea is to look at a particular C[i], then take the maximum weighted sum for an m-subsequence ending at C[i], and finally take the max of all such values over all i. This will give us our answer. Now note that when you look at an m-subsequence ending at C[i], and take the maximum weighted sum, this is equivalent to taking the maximum weighted sum of an (m-1)-subsequence, contained in C[0] to C[i-1]. And this is a smaller problem which is identical to our original one. So we use recursion. To avoid double calling to functions, we make a table of values f[i][j], where f[i-i][j] is the answer to the problem which is identical to our problem with n replaced by i and m replaced by j. That is, we build a table of f[i][j], and our final answer is f[n-1][m] (that is, we use memoization). Now noting that only the previous column is required to compute an entry f[i][j], it is enough to keep only arrays. Those arrays are 'a' and 'b'.
Sorry for the long length, can't help it. :(
Try 0/1 Knapsack without repetition approach where at each step we decide whether to include an item or not.
Let MWS(i, j) represent the optimal maximum weighted sum of the sub-problem C[i...N] where i varies from 0 <= i <= N and 1 <= j <= M, and our goal is to find out the value of MWS(0, 1).
MWS(i, j) can be represented in the recursive ways as follow.
I am leaving the boundary conditions handling as an exercise for you.
Your general approach is correct. But there is a problem with your algorithm.
You could replace the body of the inner loop
best = max = 0;
for(j=0;j<y;j++){
max += (j+1) * C[j];
}
for(i=y-1;i<x+1;i++){
best = a[i-1] + y * C[i];
max = (best>max) ? best : max;
}
b[x] = max;
with
b[x] = MAX(b[x-1],a[x-1] + y * C[x]);
This will improve the time complexity of the algorithm. I.e. avoid recomputing b[i] for
all i < x. A common trait in dynamic programming.
Related
This is my homework:
I haven't tried to write the part of Natural Logarithm because I can't solve the part of Exponential.
This is the the approximations of Exponential in C using Taylor Series expansion I wrote.
However, it returns inf. What did I do wrong?
#include <stdio.h>
// Returns approximate value of e^x
// using sum of first n terms of Taylor Series
float exponential(int n, float x)
{
float sum = 1.0f; // initialize sum of series
for (int a = n; a >= 0; ++a ) {
while (x * sum / a < 0.00001) {
break;
}
sum = 1 + x * sum / a;
return sum;
}
}
int main()
{
int n = 0;
float x = 1.0f;
printf("e^x = %.5f", exponential(n, x));
return 0;
}
With How do I ask and answer homework questions? in mind, I will give you a few things to have a careful look at.
From comment by Spektre:
from a quick look you are dividing by zero in while (x * sum / a < 0.00001) during first iteration of for loop as a=n and you called the function with n=0 ... also your code does not match the expansion for e^x at all
Have a look at the for loop:
for (int a = n; a >= 0; ++a )
What is the first value of a? The second? The third?
Keep in mind that the values are determined by ++a.
When will that loop end? It is determined by a >= 0. When is that false?
What is this loop doing?
while (x * sum / a < 0.00001) {
break;
}
I suspect that you programmed "English to C", as "do the outer loop while ...", which is practically from the assignment.
But the loop does something else. Apart from risking the division by 0 mentioned above, if the condition is true it will stay true and cause an endless loop, which then however is immediatly canceled in the first iteration.
The head of your function float exponential(int n, float x) expects n as a parameter. In main you init it with 0. I suspect you are unclear about where that value n is supposed to come from. In fact it is unknown. It is more a result of the calculation than an input.
You are supposed to add up until something happens.
You do not actually ever need the value of n. This means that your for loop is meaningless. The inner loop (though currently pointless) is much closer to your goal.
I will leave it at this for now. Try to use this input.
Feel free to edit the code in your question with improvements.
(Normally that is not appreciated, but in case of homework dialog questions I am fine with it.)
Your current implementation attempt is quite a bit off. Therefore I will describe how you should approach calculating such a series as given in your quesiton.
Let's look at your first formula:
You need to sum up terms e(n) = x^n / n!
To check with your series: 1 == x^0 / 0! - x == x^1 / 1! - ...
To calculate these terms, you need a simple rule how to get from e(n) to e(n+1). Looking at the formula above we see that you can use this rule:
e(n+1) = e(n) * x / (n+1)
Then you need to create a loop around that and sum up all the bits & pieces.
You are clearly not supposed to calculate x^n/n! from scratch in each iteration.
Your condition to stop the loop is when you reach the limit of 1e-5. The limit is for the new e(n+1), not for the sum.
For the other formulas you can use the same approach to find a rule how to calculate the single terms.
You might need to multiply the value by -1 in each step or do something like *x*n/(n+1) instead of *x/(n+1) etc.
Maybe you need to add some check if the formula is supposed to converge. Then maybe print some error message. This part is not clear in your question.
As this is homework, I only point into the direction and leave the implementation work to you.
If you have problems with implementation, I suggest to create a new question.
#include <stdio.h>
int main() {
float power;
printf("Enter the power of e\n");
scanf("%f", &power);
float ans = 1;
float temp = 1;
int i = 1;
while ((temp * power) / i >= 0.00001) {
temp = (temp * power) / i;
ans = ans + temp;
i++;
}
printf("%.5f", ans);
return 0;
}
I think I solved the problem
But the part about Natural Log is not solved, I will try.
I'm new to competitive programming and I participated in Codeforces #653 in which I spent the whole time solving this problem and did not submit any code because of exceeded time limits or wrong answer for test cases.
I wanted to solve this problem - https://codeforces.com/contest/1374/problem/A
You are given three integers x,y and n. Your task is to find the maximum integer k such that 0 ≤k≤ n that k mod x=y, where mod is modulo operation. Many programming languages use percent operator % to implement it.
In other words, with given x,y and n you need to find the maximum possible integer from 0 to n that has the remainder y modulo x
You have to answer t independent test cases. It is guaranteed that such k exists for each test case.
I wrote this following code:
#include <stdio.h>
int main(){
int i,t,j,k=0;
int x[60000],y[60000],n[60000],prev[60000];
scanf("%d",&t);
for(i=0; i<t; i++){
scanf("%d %d %d",&x[i],&y[i],&n[i]);
}
for(i=0; i<t; i++){
for(j=0, k=0; j<n[i]; j++ , k++){
if(j%x[i]==y[i]){
prev[i]=k;
}
}
}
for(i=0; i<t; i++){
printf("%d",prev[i]);
printf("\n");
}
return 0;
}
Everything was working fine but for some test cases I'm getting different answers.
This was the expected output
12339
0
15
54306
999999995
185
999999998
and my output was this:
12339
0
5
54306
999999995
185
999999998
I did not understand why I got 5 instead of 15 keeping all the other outputs correct and also could anyone please help me to optimize the code, its taking too long to compile for large inputs.
For the 1st part of your question, why the answer is wrong - has been answered nicely by others already. For the 2nd part about efficiency, the solution doesn't need any extra loop except the loop for iterating over the test case.
The solution could be as easy as this:
k = n - ((n - y) % x)
For example:x = 7, y = 5, n = 12345. Then,
k = 12345 - ((12345 - 5) % 7)
= 12339
This small piece of code could get you accepted:
#include <stdio.h>
int main()
{
int t, x, y, n;
scanf("%d", &t);
while (t > 0) {
scanf("%d %d %d", &x, &y, &n);
printf("%d\n", n - ((n - y) % x));
t--;
}
}
The reason you were getting TLE was because your code was taking too long. As I can see n could be upto 10^9 and so a O(N) solution would easily time-out at such constraints. Add to that, the fact that your code would be given upto 5*10^4 test cases. So, for your code to work, it should be much faster than O(N) time complexity. I have explained a better approach below which would satisfy the given constraints.
Optimised Approach :
For each test case, we are given x, y, n. And we have to find the largest number( let's say ans) between 0 to n such that ans%x = y.
Let's first find the remainder when we divide n by x. So, remainder = n%x. Now, if the remainder >= y, this means that we would have to reduce n such that it will leave a smaller remainder that is => a remainder equal to y. For this, we can simply reduce n by (remainder - y) amount.
Example :
For better understanding, lets see an example where
x = 10, y = 5, n = 16.
In this case remainder = n%x = 6. Now remainder > y, so we can just reduce our n by (remainder - y), that is n now becomes 15. We see that 15%x = y and so that's our answer.
The other case we might get is remainder < y. In this case, we have to increase the remainder. But we can't increase n (since it is the upper limit). So, what we can instead do is subtract x from n. The remainder will still be same. But now we are allowed to increase n by some amount which results in remainder to be y. For that we simply increase n by an amount y - remainder, so that new remainder will be equal to y.
Example :
Let's consider example where
x = 10, y = 5 and n = 24
Here, remainder = n%x = 4. So remainder < y. We subtract x from n, so n becomes 14 but still n%x = 4, so remainder remains same. But, we now have the advantage that we can increase x so that remainder would be equal to y. Since our remainder is 1 less than required (y), we increase n by 1 (or y - remainder = 1). Thus, we have the answer = 15.
This approach has time complexity of O(1) which is far better than O(N) approach. I hope that you got the idea of the approach I was trying to explain. Below is the pseudocode for same -
Pseudocode
remainder = n%x
if (remainder >= y) // Case 1
return n - ( remainder - y ) as the answer
else // Case 2
return ( n - x ) + ( y - remainder ) as the answer
Hope this helps !
The first part of this answer will explain what's wrong in your logic. The second part will contain a plot twist.
How to get the correct answer
As you have correctly been told in comments by #ErichKitzmueller your inner loop searches k values in the range [0-n[. In other words, if you are not familiar to my mathematical notation, you are not even considering the value n that is not included in your loop search, as you do for(j=0, k=0; j<n[i]; j++ , k++).
For the record, [0-n[ means "range from to 0 to n including 0 and not including n.
If you have to search the maximum value satisfying a given requirement... why starting counting from 0? You just need starting from the right limit of the range and loop backwards. The first k you will find satisfying the condition will be your output, so you'll just need to save it and exit the inner loop.
No need to find ALL the numbers satisfying the condition and overwrite them until the last is found (as you do).
The main loop of your solution would become something like that:
for(i=0; i<t; i++){
int found = 0;
for(k=n[i]; k>=0 && found==0; k--)
{
if( ( k % x[i] ) == y[i] )
{
prev[i] = k;
found = 1;
}
}
}
The plot twist (the REAL solution)
The previous solution will lead to correct answers... anyway it will be rejected as it exceeds the time limit.
Actually, all these competitive coding problems are all based on asking for a problem that in some way is simpler than it looks. In other words, it's always possible to find a way (usually after a mathematical analysis) that have a lower computational complexity than the one of the first solution that comes to your mind.
In this case we have to think:
What is the reminder of a division? y = k%x = k - x*int(k/x)
When has this expression its max? When k=n. So y = k - x*int(n/x)
So k = x*int(n/x) + y
Finally, we want make sure that this number is lower than n. If it is, we subtract x
The code becomes something like this:
#include <stdio.h>
int main(){
int i, t;
int x[60000],y[60000],n[60000],k[60000];
scanf("%d",&t);
for(i=0; i<t; i++){
scanf("%d %d %d",&x[i],&y[i],&n[i]);
}
for(i=0; i<t; i++){
int div = n[i] / x[i]; // Since div is an integer, only the integer part of the division is stored to div
k[i] = x[i] * div + y[i];
if( k[i] > n[i] )
k[i] -= x[i];
}
for(i=0; i<t; i++){
printf("%d", k[i]);
printf("\n");
}
return 0;
}
I've tested the solution on Codeforce, and it has been accepted.
the following proposed code:
cleanly compiles
performs the desired functionality
is very quick (could be made quicker via different I/O functions)
and now, the proposed code:
#include <stdio.h>
int main()
{
int x;
int y;
int n;
size_t t;
scanf("%zu",&t);
for( ; t; t-- )
{
scanf( "%d %d %d", &x, &y, &n );
printf( "%d\n", n - ((n - y) % x) );
}
return 0;
}
I have this problem:
You have n problems. You have estimated the difficulty of the i-th one
as integer ci. Now you want to prepare a problemset for a contest,
using some of the problems you've made.
A problemset for the contest must consist of at least two problems.
You think that the total difficulty of the problems of the contest
must be at least l and at most r. Also, you think that the difference
between difficulties of the easiest and the hardest of the chosen
problems must be at least x.
Find the number of ways to choose a problemset for the contest.
Input The first line contains four integers n, l, r, x (1 ≤ n ≤ 15,
1 ≤ l ≤ r ≤ 109, 1 ≤ x ≤ 106) — the number of problems you have, the
minimum and maximum value of total difficulty of the problemset and
the minimum difference in difficulty between the hardest problem in
the pack and the easiest one, respectively.
The second line contains n integers c1, c2, ..., cn (1 ≤ ci ≤ 106) —
the difficulty of each problem.
Output Print the number of ways to choose a suitable problemset for
the contest.
I tried to solve it but unfortunately I couldn't do it. I asked a friend to give me an idea and he solved it for me but i don't understand something:
Code:
#include <stdio.h>
int a[25], l, r, x, i, j, n, ans;
int main(){
scanf("%d %d %d %d", &n, &l, &r, &x);
for(i=0; i<n; i++) scanf("%d", &a[i]);
for(i=0; i<(1<<n); i++){
int s = 0;
int max = 0, min = 1e9;
for(j=0; j<n; j++){
if((i>>j)&1){
if(a[j] > max) max = a[j];
if(min > a[j]) min = a[j];
s += a[j];
}
}
if(l <= s && s <= r && max-min >= x) ans++;
}
printf("%d", ans);
return 0;
}
Why is he going through that array till i<(1<<n) if he only got n elements?
Why he does this: if((i>>j)&1) ?
I know that 1<<n is the equivalent of multiplying by a power of two and 1>>n is equivalent to integer division by 2^n but it makes no sense here.
You have n possible problems, and each one can either be included or excluded from the problem set. This means that there are 2 options for every problem, so with n problems there are 2^n options for creating possible problem sets.
With the line for(i=0; i<(1<<n); i++) you are iterating all these possible problems sets, each one identified by an integer between 0 and 2^n - 1. Next, we need to identify which problems belong to a certain problem set, and we have the integer which represents it.
To do that, we take the binary representation of that integer. It will have n bits, and lets say that each bit corresponds to a problem: if it is 1 then the problem is included, otherwise it is not. This is what the line if((i>>j)&1) is doing: it checks if the bit in position j inside the integer i is equal to 1, which means that the corresponding problem is included.
The rest is easier: from all the included problems, you calculate the minimum, maximum, and sum. Then, check if the sum s is in the valid range, and if the difference between the maximum and minimum is at least x.
I am trying to make from f_rec (recursive function) to f_iter (iterative function) but I can't.
(My logic was to create a loop to calculate the results of f_rec(n-1).
int f_rec(int n)
{
if(n>=3)
return f_rec(n-1)+2*f_rec(n-2)+f_rec(n-3);
else
return 1;
}
int f_iter(int n)
{
}
I also think that my time complexity for the f_rec is 3^n , please correct me if I'm wrong.
Thank you
There are two options:
1) Use the discrete math lessons and derive the formula. The complexity (well if #Sasha mentioned it) will be O(1) for both memory and algorithm. No loops, no recursion, just the formula.
At first you need to find the characteristic polynomial and calculate its roots. Let's asssume that our roots are r1, r2, r3, r4. Then the n'th element is F(n) = A * r1^n + B * r2^n + C * r3^n + D * r4^n, where A, B, C, D are some unknown coefficients. You can find these coefficients using your initial conditions (F(n) = 1 for n <= 3).
I can explain it on russian if you need.
2) Use additional variables to store intermediate values. Just like #6052 have answered (he has answered really fast :) ).
You can always calculate the newest value from the last three. Just start calculating from the beginning and always save the last three:
int f_iter (int n) {
int last3[3] = {1,1,1}; // The three initial values. Use std::array if C++
for (int i = 3; i <= n; ++i) {
int new_value = last3[0] + 2 * last3[1] + last3[2];
last3[0] = last3[1];
last3[1] = last3[2];
last3[2] = new_value;
}
return last3[2];
}
This solution need O(1) memory and O(n) runtime. There might exist a formula that calculates this in O(1) (there most likely is), but I guess for the sake of demonstrating the iteration technique, this is the way to go.
Your solution has exponential runtime: Every additional level spawns three evaluations, so you end up with O(3^n) operations and stack-memory.
The following is the idea
int first=1,second=1,third=1; /* if n<=3 then the respective is the answer */
for(i=4;i<=n;i++)
{
int next=first+2*second+third;
first=second;
second=third;
third=next;
}
cout<<"The answer is "<<next<<endl;
Memory is O(1) and time is O(n).
EDIT
Your recursive function is indeed exponential in time , to keep it linear you can make use
of an array F[n], and use memoization. First initialize F[] as -1.
int f_rec(int n)
{
if(n>=3)
{
if(F[n]!=-1)return F[n];
F[n]=f_rec(n-1)+2*f_rec(n-2)+f_rec(n-3);
return F[n];
}
else
return 1;
}
Just keep three variables and roll them over
start with a, b and c all equal to 1
at each step new_a is a + 2*b + c
roll over: new_c is b, new_b is a
repeat the required number of steps
A bit of an overkill, but this can be further optimized by letting the what the variables represent change in an unfolded loop, combined with (link) Duff's device to enter the loop:
int f_iter(int n){
int a=1, b=1, c=1;
if(n < 3)
return(1);
switch(n%3){
for( ; n > 2; n -= 3){
case 2:
b = c + 2*a + b;
case 1:
a = b + 2*c + a;
case 0:
c = a + 2*b + c;
}
}
return c;
}
I have written a program to print all the permutations of the string using backtracking method.
# include <stdio.h>
/* Function to swap values at two pointers */
void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* Function to print permutations of string
This function takes three parameters:
1. String
2. Starting index of the string
3. Ending index of the string. */
void permute(char *a, int i, int n)
{
int j;
if (i == n)
printf("%s\n", a);
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); //backtrack
}
}
}
/* Driver program to test above functions */
int main()
{
char a[] = "ABC";
permute(a, 0, 2);
getchar();
return 0;
}
What would be time complexity here.Isn't it o(n2).How to check the time complexity in case of recursion? Correct me if I am wrong.
Thanks.
The complexity is O(N*N!), You have N! permutations, and you get all of them.
In addition, each permutation requires you to print it, which is O(N) - so totaling in O(N*N!)
My answer is going to focus on methodology since that's what the explicit question is about. For the answer to this specific problem see others' answer such as amit's.
When you are trying to evaluate complexity on algorithms with recursion, you should start counting just as you would with an iterative one. However, when you encounter recursive calls, you don't know yet what the exact cost is. Just write the cost of the line as a function and still count the number of times it's going to run.
For example (Note that this code is dumb, it's just here for the example and does not do anything meaningful - feel free to edit and replace it with something better as long as it keeps the main point):
int f(int n){ //Note total cost as C(n)
if(n==1) return 0; //Runs once, constant cost
int i;
int result = 0; //Runs once, constant cost
for(i=0;i<n;i++){
int j;
result += i; //Runs n times, constant cost
for(j=0;j<n;j++){
result+=i*j; //Runs n^2 times, constant cost
}
}
result+= f(n/2); //Runs once, cost C(n/2)
return result;
}
Adding it up, you end up with a recursive formula like C(n) = n^2 + n + 1 + C(n/2) and C(1) = 1. The next step is to try and change it to bound it by a direct expression. From there depending on your formula you can apply many different mathematical tricks.
For our example:
For n>=2: C(n) <= 2n^2 + C(n/2)
since C is monotone, let's consider C'(p)= C(2^p):
C'(p)<= 2*2^2p + C'(p-1)
which is a typical sum expression (not convenient to write here so let's skip to next step), that we can bound: C'(p)<=2p*2^2p + C'(0)
turning back to C(n)<=2*log(n)*n^2 + C(1)
Hence runtime in O(log n * n^2)
The exact number of permutations via this program is (for a string of length N)
start : N p. starting each N-1 p. etc...
number of permutations is N + N(N-1) + N(N-1)(N-2) + ... + N(N-1)...(2) (ends with 2 since the next call just returns)
or N(1+(N-1)(1+(N-2)(1+(N-3)(1+...3(1+2)...))))
Which is roughly 2N!
Adding a counter in the for loop (removing the printf) matches the formula
N=3 : 9
N=4 : 40
N=5 : 205
N=6 : 1236
...
The time complexity is O(N!)