Binary tree and Processors (C++ Codeforces Problem) - c++

As the title says, I am trying to solve this problem which I couldn't find a solution on Youtube or somewhere else...
So here is the problem statement:
Eonathan Eostar decided to learn the magic of multiprocessor systems. He has a full binary tree of tasks with height h. In the beginning, there is only one ready task in the tree — the task in the root. At each moment of time, p processes choose at most p ready tasks and perform them. After that, tasks whose parents were performed become ready for the next moment of time. Once the task becomes ready, it stays ready until it is performed.
You shall calculate the smallest number of time moments the system needs to perform all the tasks.
Input:
The first line of the input contains the number of tests t (1≤t≤5⋅105). Each of the next t lines contains the description of a test. A test is described by two integers h (1≤h≤50) and p (1≤p≤104) — the height of the full binary tree and the number of processes. It is guaranteed that all the tests are different.
Output:
For each test output one integer on a separate line — the smallest number of time moments the system needs to perform all the tasks
Example:
input:
3
3 1
3 2
10 6
output:
7
4
173
I am a new C++ learner, so I thought of this way to solve this question:
I count all the nodes (pow(2,height)-1)
For each row I count the available nodes and put an if statement which says: If the available nodes at this row are smaller than the processors number then count++, else while the available nodes are bigger than zero (node_at_m -= m[i])
[node_at_m = Nodes available at this row; m[i] = processors number given in the question]
It gives correct answer for the first 2 cases which is (3 1) and (3 2) but it gives me wrong answer on the third case (10 6), so here is my code:
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int t, node,nodeatm, count;
cin >> t;
int n[t], m[t];
for (int i = 0; i < t; i++)
{
cin >> n[i];
cin >> m[i];
node = pow(2,n[i])-1;
count = 0;
for(int q = 0; q < n[i]; q++)
{
nodeatm = pow(2,q);
if(nodeatm <= m[i])
{
count++;
}
else
while(nodeatm > 0)
{
nodeatm -= m[i];
count++;
}
}
cout << count << endl;
}
return 0;
}
I am really not a big fan of posting Codeforces questions on here, but I couldn't find any resource for this question on the Internet...
Waiting your answers, thanks.

The problem with above code is that you are incorrectly handling the case when some of the tasks are remaining from previous level. You are assuming that all tasks must finished from one level before we move to another level.
Following is corrected code. You can see it working here:
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int t, node,nodeatm, count;
cin >> t;
int n[t], m[t];
for (int i = 0; i < t; i++)
{
cin >> n[i];
cin >> m[i];
node = pow(2,n[i])-1;
count = 0;
int rem = 0;
for(int q = 0; q < n[i]; q++)
{
nodeatm = pow(2,q) + rem ;
if(nodeatm <= m[i])
{
count++;
rem = 0;
}
else
{
while(nodeatm >= m[i])
{
nodeatm -= m[i];
count++;
}
rem = nodeatm;
}
}
if( rem )
{
count++;
}
cout << count << endl;
}
return 0;
}
Following is a bit simplified code. You can see it working here:
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int t;
cin >> t;
for (int i = 0; i < t; i++)
{
int rem = 0, n, m, count = 0;
cin >> n >> m;
for(int q = 0; q < n; q++)
{
int nodeatm = pow(2,q) + rem;
if( nodeatm < m)
{
count++;
rem = 0;
}
else
{
count += ( nodeatm/ m );
rem = ( nodeatm % m );
}
}
if( rem )
count++;
cout << count << endl;
}
return 0;
}

Related

Find largest mode in huge data set without timing out

Description
In statistics, there is a measure of the distribution called the mode. The mode is the data that appears the most in a data set. A data set may have more than one mode, that is, when there is more than one data with the same number of occurrences.
Mr. Dengklek gives you N integers. Find the greatest mode of the numbers.
Input Format
The first line contains an integer N. The next line contains N integers.
Output Format
A row contains an integer which is the largest mode.
Input Example
6
1 3 2 4 1 4
Example Output
4
Limits
1 ≤ N ≤100,000
1≤(every integer on the second line)≤1000
#include <iostream>
#include <string>
using namespace std;
#define ll long long
int main() {
unsigned int N;
while(true){
cin >> N;
if(N > 0 && N <= 1000){
break;
}
}
int arr[N];
int input;
for (int k = 0; k < N; k++)
{
cin >> input;
if(input > 0 && input <=1000){
arr[k] = input;
}
else{
k -= 1;
}
}
int number;
int mode;
int position;
int count = 0;
int countMode = 1;
for (int i = 0; i < N; i++)
{
number = arr[i];
for (int j = 0; j < N; j++)
{
if(arr[j] == number){
++count;
}
}
if(count > countMode){
countMode = count;
mode = arr[i];
position = i;
}
else if(count == countMode){
if(arr[i] > arr[position]){
mode = arr[i];
position = i;
}
}
count = 0;
}
cout << mode << endl;
return 0;
}
I got a "RTE" (run time error) and 70 pts.
Here is the code which I got 80 pts but got "TLE" (time limit exceeded):
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main() {
unsigned int N;
while(true){
cin >> N;
if(N > 0 && N <= 100000){
break;
}
}
int arr[N];
int input;
for (int k = 0; k < N; k++)
{
cin >> input;
if(input > 0 && input <=1000){
arr[k] = input;
}
else{
k -= 1;
}
}
int number;
vector<int> mode;
int count = 0;
int countMode = 1;
for (int i = 0; i < N; i++)
{
number = arr[i];
for (int j = 0; j < N; j++)
{
if(arr[j] == number){
++count;
}
}
if(count > countMode){
countMode = count;
mode.clear();
mode.push_back(arr[i]);
}
else if(count == countMode){
mode.push_back(arr[i]);
}
count = 0;
}
sort(mode.begin(), mode.end(), greater<int>());
cout << mode.front() << endl;
return 0;
}
How can I accelerate the program?
As already noted, the algorithm implemented in both of the posted snippets has O(N2) time complexity, while there exists an O(N) alternative.
You can also take advantage of some of the algorithms in the Standard Library, like std::max_element, which returns an
iterator to the greatest element in the range [first, last). If several elements in the range are equivalent to the greatest element, returns the iterator to the first such element.
#include <algorithm>
#include <array>
#include <iostream>
int main()
{
constexpr long max_N{ 100'000L };
long N;
if ( !(std::cin >> N) or N < 1 or N > max_N )
{
std::cerr << "Error: Unable to read a valid N.\n";
return 1;
}
constexpr long max_value{ 1'000L };
std::array<long, max_value> counts{};
for (long k = 0; k < N; ++k)
{
long value;
if ( !(std::cin >> value) or value < 1 or value > max_value )
{
std::cerr << "Error: Unable to read value " << k + 1 << ".\n";
return 1;
}
++counts[value - 1];
}
auto const it_max_mode{ std::max_element(counts.crbegin(), counts.crend()) };
// If we start from the last... ^^ ^^
std::cout << std::distance(it_max_mode, counts.crend()) << '\n';
// The first is also the greatest.
return 0;
}
Compiler Explorer demo
I got a "RTE" (run time error)
Consider this fragment of the first snippet:
int number;
int mode;
int position; // <--- Note that it's uninitialized
int count = 0;
int countMode = 1;
for (int i = 0; i < N; i++)
{
number = arr[i];
// [...] Evaluate count.
if(count > countMode){
countMode = count;
mode = arr[i];
position = i; // <--- Here it's assigned a value, but...
}
else if(count == countMode){ // If this happens first...
if(arr[i] > arr[position]){
// ^^^^^^^^^^^^^ Position may be indeterminate, here
mode = arr[i];
position = i;
}
}
count = 0;
}
Finally, some resources worth reading:
Why is “using namespace std;” considered bad practice?
Why should I not #include <bits/stdc++.h>?
Using preprocessing directive #define for long long
Why aren't variable-length arrays part of the C++ standard?
You're overcomplicating things. Competitive programming is a weird beast were solutions assume limited resources, whaky amount of input data. Often those tasks are balanced that way that they require use of constant time alternate algorithms, summ on set dynamic programming. Size of code is often taken in consideration. So it's combination of math science and dirty programming tricks. It's a game for experts, "brain porn" if you allow me to call it so: it's wrong, it's enjoyable and you're using your brain. It has little in common with production software developing.
You know that there can be only 1000 different values, but there are huge number or repeated instances. All that you need is to find the largest one. What's the worst case of finding maximum value in array of 1000? O(1000) and you check one at the time. And you already have to have a loop on N to input those values.
Here is an example of dirty competitive code (no input sanitation at all) to solve this problem:
#include <bits/stdc++.h>
using namespace std;
using in = unsigned short;
array<int, 1001> modes;
in biggest;
int big_m;
int N;
int main()
{
cin >> N;
in val;
while(N --> 0){
cin >> val;
if(val < 1001) {
modes[val]++;
}
else
continue;
if( modes[val] == big_m) {
if( val > biggest )
biggest = val;
}
else
if( modes[val] > big_m) {
biggest = val;
big_m = modes[val];
}
}
cout << biggest;
return 0;
}
No for loops if you don't need them, minimalistic ids, minimalistic data to store. Avoid dynamic creation and minimize automatic creation of objects if possible, those add execution time. Static objects are created during compilation and are materialized when your executable is loaded.
modes is an array of our counters, biggest stores largest value of int for given maximum mode, big_m is current maximum value in modes. As they are global variables, they are initialized statically.
PS. NB. The provided example is an instance of stereotype and I don't guarantee it's 100% fit for that particular judge or closed test cases it uses. Some judges use tainted input and some other things that complicate life of challengers, there is always a factor of unknown. E.g. this example would faithfully output "0" if judge would offer that among input values even if value isn't in range.

Function not printing any solutions

So, I need to make a function that is going to return the chromatic number of a graph. The graph is given through an adjecency matrix that the function finds using a file name. I have a function that should in theory work and which the compiler is throwing no issues for, yet when I run it, it simply prints out an empty line and ends the program.
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
int Find_Chromatic_Number (vector <vector <int>> matg, int matc[], int n) {
if (n == 0) {
return 0;
}
int result, i, j;
result = 0;
for (i = 0; i < n; i++) {
for (j = i; j < n; j++) {
if (matg[i][j] == 1) {
if (matc[i] == matc[j]) {
matc[j]++;
}
}
}
}
for (i = 0; i < n; i++) {
if (result < matc[i]) {
result = matc[i];
}
}
return result;
}
int main() {
string file;
int n, i, j, m;
cout << "unesite ime datoteke: " << endl;
cin >> file;
ifstream reader;
reader.open(file.c_str());
reader >> n;
vector<vector<int>> matg(n, vector<int>(0));
int matc[n];
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
reader >> matg[i][j];
}
matc[i] = 1;
}
int result = Find_Chromatic_Number(matg, matc, n);
cout << result << endl;
return 0;
}
The program is supposed to use an freader to convert the file into a 2D vector which represents the adjecency matrix (matg). I also made an array (matc) which represents the value of each vertice, with different numbers corresponding to different colors.
The function should go through the vector and every time there is an edge between two vertices it should check if their color value in matc is the same. If it is, it ups the second vale (j) by one. After the function has passed through the vector, the matc array should contain n different number with the highest number being the chromatic number I am looking for.
I hope I have explained enough of what I am trying to accomplish, if not just ask and I will add any further explanations.
Try to make it like that.
Don't choose a size for your vector
vector<vector<int> > matg;
And instead of using reader >> matg[i][j];
use:
int tmp;
reader >> tmp;
matg[i].push_back(tmp);

Right way of using max function and/or alternatives

So, here is my homework problem. It states "Enter five numbers five times. Every time, the program chooses the biggest number you enter, and it returns the arithmetic mean of those five largest numbers." Now, what I've done is use max function, however, I learned that it isn't useable in this way. Here is what I've tried:
#include <iostream>
using namespace std;
int main() {
int zbir = 0;
for (int i = 1; i < 6; i++) {
int a, b, c, d, e;
for (int j = 1; j < 6; j++) {
cin >> a >> b >> c >> d >> e;
}
int maks = max(a, b, c, d, e);
zbir = zbir + maks;
}
cout << zbir / 5;
}
There are two versions of max: the two-argument version, and the initializer list version. In this case, you have five arguments, so use the initializer list version:
std::max({a, b, c, d, e})
(You need to #include <algorithm> to use std::max.)
Within your code you do not need to have an inner for-loop because you are already collecting all 5 of the user numbers with the cin >> a >> b >> c >> d >> e; statement. Having a second for loop around it will cause you to collect 5 numbers from the user 25 times total.
This is an example of the alternative to using the max function in which case a single number is collected 5 times making use of an inner for-loop:
int main()
{
int sumOfMaxNums = 0;
int userNum = 0;
int maxNum = 0;
// it is a good practice to have a const that will bound the loop
// this way you can change it from here
// in other cases you can have two different const bounds, one for the inner loop and
// one for the outer loop because they may differ
const int NUM_ITERS = 5;
// This will handle asking the user to enter the numbers 5 times
for(int i = 0; i < NUM_ITERS; ++i)
{
// this loop will asks the user to enter a number 5 times and keep track of the max
for(int j = 0; j < NUM_ITERS; ++j)
{
cin >> userNum;
// here we want to set the maxNum to be the very first number that the user enters
// or we could set it to smallest negative number
if(j == 0)
{
maxNum = userNum;
}
else if(userNum > maxNum)
{
maxNum = userNum;
}
} // end of inner for-loop
sumOfMaxNums += maxNum;
} // end of outer for-loop
cout << sumOfMaxNums / static_cast<float>(NUM_ITERS) << "\n";
} // end of main
You probably want to calculate the mean as a float rather than an int, otherwise the program will round the final answer down to the nearest whole number. Also, you really don't need to use five variables to store each cycle's inputs, since you can ignore any inputs that are less than the running maximum for that cycle. This means you don't need to use std::max at all.
#include<iostream>
int main()
{
float running_total = 0;
for (int cycle = 1; cycle < 6; ++cycle)
{
float cycle_max;
for (int entry = 1; entry < 6; ++entry)
{
float input = 0;
std::cin >> input;
if (entry == 1 || input > cycle_max) cycle_max = input;
}
running_total += cycle_max;
}
std::cout << running_total / 5 << std::endl;
}

(C++) Generate first p*n perfect square numbers in an array (p and n inputted from the keyboard)

I input p and n (int type) numbers from my keyboard, I want to generate the first p*n square numbers into the array pp[99]. Here's my code:
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int i, j, n, p, pp[19];
cout<<"n="; cin>>n;
cout<<"p="; cin>>p;
i=n*p;
j=-1;
while(i!=0)
{
if(sqrt(i)==(float)sqrt(i))
{
j++;
pp[j]=i;
}
i--;
}
for(i=0; i<n*p; i++)
cout<<pp[i]<<" ";
return 0;
}
But I am encountering the following problem: If I for example I enter p=3 and n=3, it will only show me the first 3 square numbers instead of 9, the rest 6 being zeros. Now I know why this happens, just not sure how to fix it (it's checking the first n * p natural numbers and seeing which are squares, not the first n*p squares).
If I take the i-- and add it in the if{ } statement then the algorithm will never end, once it reaches a non-square number (which will be instant unless the first one it checks is a perfect square) the algorithm will stop succeeding in iteration and will be blocked checking the same number an infinite amount of times.
Any way to fix this?
Instead of searching for them, generate them.
int square(int x)
{
return x * x;
}
int main()
{
int n = 0;
int p = 0;
std::cin >> n >> p;
int limit = n * p;
int squares[99] = {};
for (int i = 0; i < limit; i++)
{
squares[i] = square(i+1);
}
for (int i = 0; i < limit; i++)
{
std::cout << squares[i] << ' ';
}
}

Program to calculate the sum of terms? c++

So im trying to write a program that will calculate the sum of terms but each term is 3 times the previous term minus the second previous term so it looks like this 0, 1, 3, 8, 21, 55 and so on. For example if the user wants 4 terms then the program should output 21. The part im having problems with is setting up the variables to store the previous number and the second previous number. This is what i have so far.
#include <iostream>
using namespace std;
int main(){
int num;
int last;
int last2;
int current;
cout << "Number of terms to be shown: ";
cin >> num;
for(int i = 0; i < num; i++){
for(int term; term <= i; i++){
//THIS IS WHERE IM STUCK
}
}
}
The way i see it is the first for loop will tell the nested for loop how many times to run. In the nested for loop i think is where the math should go (current = (last * 3) - last2) while updating the last and last2 variables to keep the term list going. And then outside the loop i would cout << current so it would display the term. Like always, any help is appreciated!
There is an Undefined Behavior in your code in:
for(int i = 0; i < num; i++){
for(int term; term <= i; i++){ // term not initiaized. and the loop is infinte
//THIS IS WHERE IM STUCK
}
}
You are using term without being intialized. Also you are stuck in the inner loop because you should increment term not i in the inner loop.
So you can make it this way:
for(int i = 0; i < num; ++i){
for(int term = 0; term <= i; ++term){
// now rock here
}
}
You would typically remember the last two values, and simply go on computing the next one:
#include <iostream>
using namespace std;
int main()
{
int num;
cout << "Number of terms to be shown: ";
cin >> num;
int p1 = 1;
int p2 = 0;
cout << p2 << " " << p1 << " ";
num -= 2;
while (num > 0)
{
int current = 3 * p1 - p2;
cout << current << " ";
p2 = p1;
p1 = current;
num--;
}
}
This is the algorithm as I see it in my head when I read your question:
unsigned term(unsigned num) {
// the previous term*3 minus the second previous term
if(num > 1) return term(num - 1) * 3 - term(num - 2);
return num; // 0 or 1
}
It uses recursion to call itself, which is a great way to visualize what needs to be done for problems like this. The function works as-is but only for small nums, or else you'll get a stack overflow. It's also rather time consuming since it's doing function calls and calculates all terms many, many times.