I'm trying to solve this problem.
The description states that some friends have a bottle of coke and they want to equally divide it in cups and I need to help the group to split the Coke bottle.
To solve this I need the height h such that, if each cup is filled with Coke up to the height h, then each person gets the same amount of coke. You may assume that no cup will needed to be filled more than its capacity.
The information given to me is the radius of the top and bottom of the cup with its height.
Input description:
The first line of input contains an integer C that determines the number of test cases. Each test case starts with a line containing two integers, N and L (1 ≤ N ≤ 100, 1 ≤ L ≤ 10^8), the number of friends in the group and the amount of Coke in the bottle, in milliliters. The second line contains three integers b, B and H (1 ≤ b ≤ B ≤ 100, 1 ≤ H ≤ 100), the radius of the smaller and the larger base, and the height of the cups, in centimeters.
The output description :
For each test case, print the value of h such that all cups must be filled up to the height h cm. Print the answer with 2 decimal places.
Example of Input:
2
1 200
5 6 8
2 350
3 3 16
Example of Output:
2.40
6.19
My solution.
With the data given in the question it was necessary to find the radius of the top of the coke amount (like a frustum inside a frustum O.o where the data given correspond to the outside frustum)
With the radius of the coke amount the binary search algorithm can 'guess' the best h.
#include <stdio.h>
#include <math.h>
#define EPS 0.001
typedef long long lld;
int main(){
lld c,n,l,b,B,H; //names are described in the input
scanf("%lld",&c);
for (lld i = 0; i < c; ++i) {
scanf("%lld %lld %lld %lld %lld",&n,&l,&b,&B,&H);
double v = l/n;//volume expected for each cup
double ini = 0,fim = H, mid = 0.0; //mid will be the 'h'
double v_approximate = 0;
while(fabs(v - v_approximate) > EPS){
mid = (ini + fim)/2.0;
double tmp = b + (B-b)*mid/H; //this is the radius of the coke top
v_approximate = (M_PI*mid/3.0)*(tmp*tmp + tmp*b + b*b);
if(v_approximate == v)
break;
else if(v_approximate > v)
fim = mid;
else
ini = mid;
}
printf("%.2lf\n",mid);
}
}
This code gives 10% of wrong answer. This is the first time that i tried to use approximation to solve a math question. What am i missing ?
Related
I was solving a coding problem and came across this one. It states :
We have an infinitely planar cartesian coordinate system on which N points are plotted. Cartesian coordinates of the point I am represented by (Xi, Yi).
Now we want to draw (N-1) line segments which may have arbitrary lengths and the points need not lie on the lines. The slope of each line must be 1 or -1.
Let's denote the minimum distance we have to walk from a point I to reach a line by Di and let's say a = max(D1, D2, D3,..., DN). We want this distance to be minimum as possible.
Thus we have to plot lines in such a way that it minimizes 'a' and compute a*sqrt(2)
Constraints :
1 <= T <= 100
2 <= N <= 10^4
|Xi|, |Yi| <= 10^9 for each valid i
Here T denotes number of test cases.
Sample input 1 :
N = 3
Points : (0,0) , (0,1) , (0,-1)
Sample output 1 :
0.5
Explanation: We should draw lines described by equations y−x+0.5=0 and y−x−0.5=0
Sample input 2 :
N = 3
Points : (0,1) , (1,0) , (-1,0)
Sample output 2 :
0
Explanation: We should draw lines described by equations y−x−1=0 and y+x−1=0
Output format :
For each test case, print a single line containing one real number — the minimum distance a multiplied by sqrt(2). Your answer will be considered correct if its absolute or relative error does not exceed 10^(-6).
Time limit: 1 sec
My understanding is as the slopes are 1 or -1 the equations of the lines would be y = x + c or y = -x + c and we just have to find the y-intercept c which minimizes the distance 'a' in the problem. Also, the minimum distance from a point to the line is the length of the perpendicular to the line.
So I am having difficulty to devise an algorithm which will check all possible values of 'c' and find the optimal one.
Let us denote M[i] the point (x[i], y[i])
The fist step is to compute the distance between a point M(x, y) and a line D, slope of which is equal to +/-1.
Let us denote D and D' the lines
D: y + x + c = 0
D': y - x + c = 0
Then, a few calculations allow to show that
the distance between M and D is equal to d(M, D) = abs(y + x + c)/sqrt(2)
the distance between M and D' is equal to d(M, D') = abs(y - x + c)/sqrt(2)
Let us now consider two different points, for example M[0] and M[1], and let us calculate the minimum distance between these two points and a line D of parameter c and slope +/-1.
Formally, we have two find the minimum, over c and slope, of
max(d(M[0], D), d(M[1], D))
If the slope is -1, i.e. if the equation is y+x+c=0, one can easily show the the optimum c parameter is equal to
c = -(x0 + y0 + x1 + y1)/2
The corresponding distance is equal to abs(x0+y0-x1-y1)/(2*sqrt(2))
If the slope is 1, i.e. if the equation is y-x+c=0, one can show the the optimum c parameter is equal to
c = (x0 - y0 + x1 - y1)/2
The corresponding distance is equal to abs(y0 - x0 - y1 + x1)/(2*sqrt(2))
Therefore, the minimum distance from these two points to an optimal line is the minimum of the previous two distances.
This leads to define the following quantities, for each points M[i]:
a|i] = y[i] - x[i]
b[i] = y[i] + x[i]
And then to define a distance between points M[i] and M[j] as :
d(M[i], M[j]) = min (abs(b[i]-b[j]), abs(a[i]-a[j]))
The proposed algorithm consists in finding the pair (M[i], M[j]) such that this distance is minimized.
Then the wanted result is equal to half this distance.
This corresponds to consider that a line will pass through the distant points (according to the defined distance), except the two closest ones, for which we will draw a line just in between.
(EDIT)
The complexity is not O(n^2) as previously stated.
The complexity to find the min of d(M[i], M[j]) is O(N logN).
This is obtained by sorting the a[i] and to get the min of the differences between adjacent values, i.e. min(a[i+1] - a[i]).
Then by doing the same for the b[i], and finally taking the minimum of the two obtained values.
The link for the question is as follows: http://codeforces.com/problemset/problem/478/C
You have r red, g green and b blue balloons. To decorate a single table for the banquet you need exactly three balloons. Three balloons attached to some table shouldn't have the same color. What maximum number t of tables can be decorated if we know number of balloons of each color?
Your task is to write a program that for given values r, g and b will find the maximum number t of tables, that can be decorated in the required manner.
Input:
The single line contains three integers r, g and b (0 ≤ r, g, b ≤ 2·10^9) — the number of red, green and blue baloons respectively. The numbers are separated by exactly one space.
Output:
Print a single integer t — the maximum number of tables that can be decorated in the required manner.
So, what I did was, in a greedy manner, searched for the maximum and minimum value each time and subtracted 2 and 1 respectively if possible. Here is my code:
int main (void)
{
int ans=0,r,g,b;
cin>>r>>g>>b;
while (1)
{
int a1 = maxfind(r,g,b);
int a2 = minfind(r,g,b);
//ans++;
if (a1 >= 2 && a2 >= 1)
{
ans++;
if (indma == 1)
r = r-2;
else if (indma == 2)
g = g-2;
else
b = b-2;
if (indmi == 1)
r = r-1;
else if (indmi == 2)
g = g-1;
else
b = b-1;
}
else if (r == 1 && g == 1 && b == 1)
{
ans++;
break;
}
else
break;
}
cout<<ans<<"\n";
int maxfind(int r, int g, int b)
{
indma = 0;
int temp = INT_MIN;
if (r >= temp)
{
temp = r;
indma = 1;
}
if (g >= temp)
{
temp = g;
indma = 2;
}
if (b >= temp)
{
temp = b;
indma = 3;
}
return temp;
}
Similar is the function for findmin and I make sure that it's not the same number chosen in case the maximum and minimum values are same. However, since the limit is 2*10^9, obviously, this surpasses the Time limit. How can I optimise it? Thanks!
Edit: You can easily find sample test cases in the link for the question. However, I am still adding one of them.
Input
5 4 3
output
4
Explanation: In the first sample you can decorate the tables with the following balloon sets: "rgg", "gbb", "brr", "rrg", where "r", "g" and "b" represent the red, green and blue balls, respectively.
You can split this problem into two scenarios, either you use all the balloons(with 0, 1, or 2 left over), or you don't because there is too many of one color and not enough of the other two.
If you use all the balloons, the answer is simply (r+g+b)/3
if you don't use all the balloons, then the answer is equal to the sum of the lower 2 of the three numbers.
t = min((r+g+b)/3,r+g+b-max(r,g,b))
Without looking at the problem but just at your code:
If the smallest number is less than the middle number and at least two less than the largest number before any iteration then this is true after that iteration as well (because the smallest number will now be less than the number that was the largest, and it will be two less than the number that was the middle one). In that case you can figure out exactly what will happen throughout your algorithm (the largest number will be decreased by two until it is not the largest anymore, and then the two largest numbers will be decreased by two in turn). So you can figure out exactly what ans will be without actually doing all the iterations.
If the two smallest numbers are equal and the largest is at least three larger then in the next two iterations both smallest numbers will be decreased by 1 once, while the largest will be decreased by 2 twice. You can calculate how often that happens.
After that you end up with (x, x+1, x+1), (x, x, x+2), (x, x, x+1) or (x, x, x). Here you can also predict what will happen in the next iteration or the next two iterations. It's a bit complicated, but not very complicated. For example, if three numbers are (x, x, x+1) then the next three numbers will be (x-1, x, x-1) which is the same pattern again.
Example: Start with (10^9, 10^9 + 1, 10^9 + 1000): You will 500 times subtract 1 from the first and 2 from the last number, giving (10^9 - 500, 10^9 + 1, 10^9 + 0). Then you will 10^9 - 500 times decrease the first number by 1, and since the number is even you will decrease each of the other two numbers by two (10^9 - 500) / 2 times. At that point you have (0, 501, 500) and your algorithm ends with ans = 10^9.
Now this shows how to do the calculation in constant time. It doesn't show whether this gives the correct solution.
How can I optimise this to run in an efficient manner?
By looking at the problem more closely. The brute force approach will not work (unfortunately).
Fortunately, the numbers can be calculated in a single closed equation without resorting to recursion or looping.
Let's try a derivation: You start with (r, g, b) balloons. The upper limit of tables is certainly sum(r, g, b) / 3 (integer division, i.e. round down) because you need at least three times as many balloons as tables.
What about the less than-optimal cases? To decorate a table, you need two balloons of different colors but you do not care about the color of the third one.
Let's assume that you have fewest green (min(r, b, g) = g) balloons. So you can certainly decorate g tables as long as you have enough baloons in total (already covered). How many more tables can you decorate?
Assuming you did not use up all balloons yet (i.e. g < sum(r, b, g) / 3) you have used up 2 x g balloons of the other colors, i.e. you have a total of sum(r, b) - 2 x g balloons left. This can be an arbitrary combination of the available red and blue balloons since we can shuffle them around as we like.
If we assume, that the red (r) balloons are the second least frequent (i.e. most balloons are blue), we can decorate at most min(r, sum(r, b) - 2 x g) more tables. We either run out of red balloons or we run out of balloons, whichever one happens first.
Since we already covered the case of running out of balloons, we can ignore the second term of min(r, sum(r, b) - 2 x g).
So indeed, the number of tables is min(sum(r, b, g) / 3, min(r + b, r + g, b + g)) or simplified min(sum(r, b, g) / 3, sum(r, b, g) - max(r, b, g)), or, colloquially, the minimum of a third of the total number and the sum of the two least frequent colors.
I'm currently doing the this problem for own practice. I manage to pass all the testcases, so I can't figure out whats wrong. My code is:
#include <iomanip>
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
int main(){
int num = 1;
while(true){
string line,stringRes;
getline(cin,line);
if(cin.eof()){break;}
long double shrinks = atof(line.c_str());
long double triangels = pow(3,shrinks);
long double length = 3/pow(2,shrinks);
long double res = floor(triangels* length * 3);
int i = 0;
while(res >= 10){
i++;
res = res/10;
};
if(shrinks == 1){
printf("Case %d: %d\n",num ,1);
}else{
printf("Case %d: %d\n",num ,i+1);
}
num++;
}
return 0;
}
for exampel when I input 1000 I get 178 and 10000 I get 1762.
Input Sample
0
1
5
10
100
Output Samle
Case 1: 1
Case 2: 1
Case 3: 2
Case 4: 3
Case 5: 19
For each case, display the case number followed by the number of decimal digits required to represent the integer portion of the circumference for the given number of iterations. Follow the format of the sample output.
The reason you get the wrong result is, as described earlier: you get overflow by using pow, but also because you - as you seem to have realized - used 3 as your start side length.
Here is an alternative, and correct, solution that is a bit shorter (without overflow):
The circumference (or perimeter) P(n) of a Sierpinski triangle of order n >= 0 can be shown to be:
P(n) = 3^(n + 1) / 2^n
I don't provide a proof since it's not necessary to solve the problem. However, it's rather easy to understand that this must be the case. One way is by calculating the perimeter of the first few orders of the Sierpinski triangle: 3, 9/2, 27/4, 81/8, ..., another is to think about how the circumference changes when you (1) "shrink" the shape by a factor of ½ and (2) "extend" the triangle by a factor of 3.
The number of digits D(x) in any natural number (of base 10) x is:
D(x) = 1 + floor(log10(x))
So to calculate the number of decimal digits in the Sierpinski perimeter of order n we calculate the number of digits in the integer part of P(n) = 3^(n + 1) / 2^n, i.e. D(floor(P(n))), which is also the solution to the problem:
D(floor(P(n))) = 1 + floor(log10(3^(n + 1) / 2^n)) = /log(a/b) = log(a) - log(b)/ =
= 1 + floor(log10(3^(n + 1)) - log10(2^n)) = /log10(a^b) = b * log10(a)/ =
= 1 + floor((n + 1) * log10(3) - n * log10(2))
C++ implementation that solves the problem:
/** Calculates the number of digits in the integer part of the perimeter of the Sierpinski triangle of order n */
/** Author: Fredrik Präntare, Date: 19/3/2016 */
#include <iostream>
#include <algorithm> // log10, floor
using namespace std;
int main(){
int c = 1, n;
while(scanf("%d", &n) != EOF){
int D_p = 1 + floor((n + 1) * log10(3) - n * log10(2));
printf("Case %d: %d\n", c, D_p);
c++;
}
}
You are overflowing the value of triangels. When you have
long double triangels = pow(3,shrinks);
Where shrinks = 10000 gives: 1.6313501853426258743032567291812e+4771.
The range of a long double where sizeof(long double) == 8 is 1.7E +/- 308.
More than likely you will need to use modular exponentiation to solve this problem.
I'm looking for an algorithm to find two integer values x,y such that their product is as close as possible to a given double k while their difference is low.
Example: The area of a rectangle is k=21.5 and I want to find the edges length of that rectangle with the constraint that they must be integer, in this case some of the possible solutions are (excluding permutations) (x=4,y=5),(x=3,y=7) and the stupid solution (x=21,y=1)
In fact for the (3,7) couple we have the same difference as for the (21,1) couple
21.5-3*7=0.5 = 21.5-21*1
while for the (4,5) couple
21.5-4*5=1.5
but the couple (4,5) is preferable because their difference is 1, so the rectangle is "more squared".
Is there a method to extract those x,y values for which the difference is minimal and the difference of their product to k is also minimal?
You have to look around square root of the number in question. For 21.5 sqrt(21.5) = 4.6368 and indeed the numbers you found are just around this value.
You want to minimize
the difference of the factors X and Y
the difference of the product X × Y and P.
You have provided an example where these objectives contradict each other. 3 × 7 is closer to 21 than 4 × 5, but the latter factors are more square. Thus, there cannot be any algorithm which minimizes both at the same time.
You can weight the two objectives and transform them into one, and then solve the problem via non-linear integer programming:
min c × |X × Y - P| + d × |X – Y|
subject to X, Y ∈ ℤ
X, Y ≥ 0
where c, d are non-negative numbers that define which objective you value how much.
Take the square root, floor one integer, ceil the other.
#include <iostream>
#include <cmath>
int main(){
double real_value = 21.5;
int sign = real_value > 0 ? 1 : -1;
int x = std::floor(std::sqrt(std::abs(real_value)));
int y = std::ceil(std::sqrt(std::abs(real_value)));
x *= sign;
std::cout << x << "*" << y << "=" << (x*y) << " ~~ " << real_value << "\n";
return 0;
}
Note that this approach only gives you a good distance between x and y, for example if real_value = 10 then x=3 and y=4, but the product is 12. If you want to achieve a better distance between the product and the real value you have to adjust the integers and increase their difference.
double best = DBL_MAX;
int a, b;
for (int i = 1; i <= sqrt(k); i++)
{
int j = round(k/i);
double d = abs(k - i*j);
if (d < best)
{
best = d;
a = i;
b = j;
}
}
Let given double be K.
Take floor of K, let it be F.
Take 2 integer arrays of size F*F. Let they be Ar1, Ar2.
Run loop like this
int z = 0 ;
for ( int i = 1 ; i <= F ; ++i )
{
for ( int j = 1 ; j <= F ; ++j )
{
Ar1[z] = i * j ;
Ar2[z] = i - j ;
++ z ;
}
}
You got the difference/product pairs for all the possible numbers now. Now assign some 'Priority value' for product being close to value K and some other to the smaller difference. Now traverse these arrays from 0 to F*F and find the pair you required by checking your condition.
For eg. Let being closer to K has priority 1 and being smaller in difference has priority .5. Consider another Array Ar3 of size F*F. Then,
for ( int i = 0 ; i <= F*F ; ++i )
{
Ar3[i] = (Ar1[i] - K)* 1 + (Ar2[i] * .5) ;
}
Traverse Ar3 to find the greatest value, that will be the pair you are looking for.
So i'm implementing a heuristic algorithm, and i've come across this function.
I have an array of 1 to n (0 to n-1 on C, w/e). I want to choose a number of elements i'll copy to another array. Given a parameter y, (0 < y <= 1), i want to have a distribution of numbers whose average is (y * n). That means that whenever i call this function, it gives me a number, between 0 and n, and the average of these numbers is y*n.
According to the author, "l" is a random number: 0 < l < n . On my test code its currently generating 0 <= l <= n. And i had the right code, but i'm messing with this for hours now, and i'm lazy to code it back.
So i coded the first part of the function, for y <= 0.5
I set y to 0.2, and n to 100. That means it had to return a number between 0 and 99, with average 20.
And the results aren't between 0 and n, but some floats. And the bigger n is, smaller this float is.
This is the C test code. "x" is the "l" parameter.
//hate how code tag works, it's not even working now
int n = 100;
float y = 0.2;
float n_copy;
for(int i = 0 ; i < 20 ; i++)
{
float x = (float) (rand()/(float)RAND_MAX); // 0 <= x <= 1
x = x * n; // 0 <= x <= n
float p1 = (1 - y) / (n*y);
float p2 = (1 - ( x / n ));
float exp = (1 - (2*y)) / y;
p2 = pow(p2, exp);
n_copy = p1 * p2;
printf("%.5f\n", n_copy);
}
And here are some results (5 decimals truncated):
0.03354
0.00484
0.00003
0.00029
0.00020
0.00028
0.00263
0.01619
0.00032
0.00000
0.03598
0.03975
0.00704
0.00176
0.00001
0.01333
0.03396
0.02795
0.00005
0.00860
The article is:
http://www.scribd.com/doc/3097936/cAS-The-Cunning-Ant-System
pages 6 and 7.
or search "cAS: cunning ant system" on google.
So what am i doing wrong? i don't believe the author is wrong, because there are more than 5 papers describing this same function.
all my internets to whoever helps me. This is important to my work.
Thanks :)
You may misunderstand what is expected of you.
Given a (properly normalized) PDF, and wanting to throw a random distribution consistent with it, you form the Cumulative Probability Distribution (CDF) by integrating the PDF, then invert the CDF, and use a uniform random predicate as the argument of the inverted function.
A little more detail.
f_s(l) is the PDF, and has been normalized on [0,n).
Now you integrate it to form the CDF
g_s(l') = \int_0^{l'} dl f_s(l)
Note that this is a definite integral to an unspecified endpoint which I have called l'. The CDF is accordingly a function of l'. Assuming we have the normalization right, g_s(N) = 1.0. If this is not so we apply a simple coefficient to fix it.
Next invert the CDF and call the result G^{-1}(x). For this you'll probably want to choose a particular value of gamma.
Then throw uniform random number on [0,n), and use those as the argument, x, to G^{-1}. The result should lie between [0,1), and should be distributed according to f_s.
Like Justin said, you can use a computer algebra system for the math.
dmckee is actually correct, but I thought that I would elaborate more and try to explain away some of the confusion here. I could definitely fail. f_s(l), the function you have in your pretty formula above, is the probability distribution function. It tells you, for a given input l between 0 and n, the probability that l is the segment length. The sum (integral) for all values between 0 and n should be equal to 1.
The graph at the top of page 7 confuses this point. It plots l vs. f_s(l), but you have to watch out for the stray factors it puts on the side. You notice that the values on the bottom go from 0 to 1, but there is a factor of x n on the side, which means that the l values actually go from 0 to n. Also, on the y-axis there is a x 1/n which means these values don't actually go up to about 3, they go to 3/n.
So what do you do now? Well, you need to solve for the cumulative distribution function by integrating the probability distribution function over l which actually turns out to be not too bad (I did it with the Wolfram Mathematica Online Integrator by using x for l and using only the equation for y <= .5). That however was using an indefinite integral and you are really integration along x from 0 to l. If we set the resulting equation equal to some variable (z for instance), the goal now is to solve for l as a function of z. z here is a random number between 0 and 1. You can try using a symbolic solver for this part if you would like (I would). Then you have not only achieved your goal of being able to pick random ls from this distribution, you have also achieved nirvana.
A little more work done
I'll help a little bit more. I tried doing what I said about for y <= .5, but the symbolic algebra system I was using wasn't able to do the inversion (some other system might be able to). However, then I decided to try using the equation for .5 < y <= 1. This turns out to be much easier. If I change l to x in f_s(l) I get
y / n / (1 - y) * (x / n)^((2 * y - 1) / (1 - y))
Integrating this over x from 0 to l I got (using Mathematica's Online Integrator):
(l / n)^(y / (1 - y))
It doesn't get much nicer than that with this sort of thing. If I set this equal to z and solve for l I get:
l = n * z^(1 / y - 1) for .5 < y <= 1
One quick check is for y = 1. In this case, we get l = n no matter what z is. So far so good. Now, you just generate z (a random number between 0 and 1) and you get an l that is distributed as you desired for .5 < y <= 1. But wait, looking at the graph on page 7 you notice that the probability distribution function is symmetric. That means that we can use the above result to find the value for 0 < y <= .5. We just change l -> n-l and y -> 1-y and get
n - l = n * z^(1 / (1 - y) - 1)
l = n * (1 - z^(1 / (1 - y) - 1)) for 0 < y <= .5
Anyway, that should solve your problem unless I made some error somewhere. Good luck.
Given that for any values l, y, n as described, the terms you call p1 and p2 are both in [0,1) and exp is in [1,..) making pow(p2, exp) also in [0,1) thus I don't see how you'd ever get an output with the range [0,n)