Exceeding memory limit or time limit - c++

I'm attempting to create a program that will multiply 3 not equal positions from vector 1 ('V1'), and find the maximum multiplication.
I'm using 3 'for' loops for counting and writing. The program gets the position amount 'N', then all 'N' numbers in 'input.txt'. After that, it gets the greatest position 'max' and writes it in 'output.exe'.
But I need to keep the program as efficient as possible, 16 MB memory limit and 1 second time limit (I get 1.004 second and 33 MB). Is there a more efficient way to do this?
#include <vector>
#include <fstream>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int N;
long long max = -9223372036854775807;
int input;
vector<long long> V1;
ifstream file1;
file1.open("input.txt");
file1 >> N;
V1.resize(N);
for (int i = 0; i < N; i++)
{
file1 >> V1[i];
}
for (int i = 0; i < N; i++)
for (int j = 0; j < i; j++)
for (int k = 0; k < j; k++)
if (V1[i] * V1[j] * V1[k] > max)
{
max = V1[i] * V1[j] * V1[k];
}
ofstream file2;
file2.open("output.txt");
file2 << max;
file2.close();
}
File Input.txt
5
10 10 10 -300 - 300

From looking at what you have done, you have to find the greatest of the product of 3 numbers in a given input vector.
Just sort vector V1 and output the max of (product of 1st 3 elements or 1st and last 2 elements). This is efficient in both space and time.
Like this:
sort(V1.begin(),V1.end(),greater<int>()) //sorts in descending order
int n = V1.size()-1;
output max(V1[0] * V1[1] * V1[2], V1[0] * V1[n] * V1[n-1])

The first, which comes to my mind - why do you store these values? You only need the single maximum value - there is no need to store all these values, push them, and, moreover, sort them out.
Another important notices:
You have a vector of long long, but you read ints. Since you have big numbers in your input, use long long everywhere
Pushing an item and popping it back is senseless - you should have checked it before pushing to avoid two unnecessary operations
Anyway, you don't need to compare i, j, k for equivalence at all - they are never equal according to your loop restrictions
Pushing items to an array when you know their number is wrong. It takes more time to extend a vector. You may want to resize it to the given size.
Probably, this code will meet your memory \ time requirements:
int N;
long long maximum = -9223372036854775807; // Subject to limits.h LLONG_MIN usage
vector<long long> V1;
ifstream file1;
file1.open("input.txt");
file1 >> N;
V1.resize(N);
for (int i = 0; i < N; i++){
file1 >> V1[i];
}
file1.close();
for (int i = 0; i < N; i++)
for (int j = 0; j < i; j++)
for (int k = 0; k < j; k++)
if (V1[i] * V1[j] * V1[k] > maximum)
maximum = V1[i] * V1[j] * V1[k];
ofstream file2;
file2.open("output.txt");
file2 << maximum;
file2.close();

Well, as soon as I see size and time reduction, I tend to remove all unnecessary language goodies, because they do help in proper programming but only come at a resource expense.
So if you really wanted to keep all products of different indices of a list of values, I would advice you to throw away vectors, push and pop and use fixed size arrays.
But before that low-level optimisation, we must think of all possible algorithmic optimisations. You only want be biggest products from all possible from three different values taken from a list. But for positive numbers, a >= b <=> a *c >= b *c and the product of two negative numbers is positive.
So the highest product may only come from:
product of three highest positive values
product of one highest positive value and two lowest negative values (highest in absolute value)
product of three highest negative values if there are no positive values
So you do not even need to load the full initial vector but just keep:
Three highest positive values
Three highest negative values
Two lowest negative values
You get them by storing them at read time in O(n) time and only store eight values. If you only have five values, it is not efficient at all, but it will be linear in time and constant in size whatever number of values you process.
Possible implementation:
#include <iostream>
#include <fstream>
#include <climits>
using namespace std;
class Max3 {
long long pmax[3];
long long nmax[3];
long long nmin[2];
void push(long long *record, long long val, size_t pos) {
for(size_t i=0; i<pos; i++) {
record[i] = record[i + 1];
}
record[pos] = val;
}
void set(long long *record, long long val, size_t sz) {
for (size_t i=1; i<sz; i++) {
if (val < record[i]) {
push(record, val, i - 1);
return;
}
}
push(record, val, sz - 1);
}
public:
Max3() {
size_t i;
for (i=0; i<sizeof(pmax)/sizeof(pmax[0]); i++)
pmax[i] = 0;
for (i=0; i<sizeof(nmin)/sizeof(nmin[0]); i++)
nmin[i] = 0;
for (i=0; i<sizeof(nmax)/sizeof(nmax[0]); i++)
nmax[i] = LLONG_MIN;
}
void test(long long val) {
if (val >= *pmax) {
set(pmax, val, 3);
}
else if (val <= 0) {
if (val <= *nmin) {
set(nmin, -val, 2);
}
if (val >= *nmax) {
set(nmax, val, 3);
}
}
}
long long getMax() {
long long max = 0, prod, pm;
if ((prod = pmax[0] * pmax[1] * pmax[2]) > max)
max = prod;
if (pmax[2] > 0)
pm = pmax[2];
else if (pmax[1] > 0)
pm = pmax[1];
else
pm = pmax[0];
if ((prod = nmin[0] * nmin[1] * pm) > max)
max = prod;
if ((prod = nmax[0] * nmax[1] * nmax[2]) > max)
max = prod;
return max;
}
};
int main() {
int N;
long long input;
Max3 m3;
ifstream file1;
file1.open("input.txt");
file1 >> N;
for (int i = 0; i < N; i++){
file1 >> input;
m3.test(input);
}
file1.close();
ofstream file2;
file2.open("output.txt");
file2 << m3.getMax();
file2.close();
return 0;
}
The code is slightly more complex, but the program size is only 35 KB, with little dynamic allocation.

After replacing the 'for' loops with a sort of vector 1 'V1' (in descending order), the program compares the products 'V1[0] * V1[1] * V1[2]' and 'V1[0] * V1[N] * V1[N - 1', and then prints the maximum in file output.txt:
#include <vector>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{
int N;
long long max = -9223372036854775807;
int input;
vector<long long> V1;
ifstream file1;
file1.open("input.txt");
file1 >> N;
V1.resize(N);
for (int i = 0; i < N; i++){
file1 >> V1[i];
}
sort(V1.begin(), V1.end(), greater<int>());
N -= 1;
max = V1[0] * V1[1] * V1[2];
if (max < V1[0] * V1[N] * V1[N - 1])
max = V1[0] * V1[N] * V1[N - 1];
ofstream file2;
file2.open("output.txt");
file2 << max;
file2.close();
}

Related

Different Results for int and long long

So, I was doing a question that asked us to divide an array into two parts such that the difference between the sum of elements of both of the parts shall be minimum.
Say A = [3 2 7 4 1]. So, minimum difference is generated when [2 3 4] and [7 1] are the two parts, i.e. difference = (2+3+4)-(7+1) = 1.
My approach was pretty naive, which basically computed all different subsets of the given array, and calculate the absolute difference with its complementary array, and report the minimum of these values.
When I used int my program it gave the correct answers for all but two test cases. In these test cases, the inputs were exceeding the limits of int. So, I changed it to long long, but this gave very weird results. It even started giving wrong results for the previously correct results.
CORRECT OUTPUT GIVING CODE (using int):
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int min_diff = INT_MAX;
void subsetGen(vector <int> &curr,vector <int> &v, int n, int index, int sum)
{
if (!curr.empty())
{
int sum_1 = accumulate(curr.begin(), curr.end(), 0);
int diff = abs(2*sum_1 - sum);
min_diff = (diff<min_diff) ? diff : min_diff;
}
for (int i = index; i < v.size(); i++)
{
curr.push_back(v[i]);
subsetGen (curr, v, n, i+1, sum);
curr.pop_back(); // Backtracking
}
return;
}
int main()
{
int n, sum = 0;
cin >> n;
vector <int> v (n, 0);
for (int i=0; i<n; i++)
{
cin >> v[i];
sum += v[i];
}
vector <int> curr;
subsetGen(curr,v,n,0,sum);
cout << min_diff;
return 0;
}
INCORRECT OUTPUT GIVING CODE (using long long):
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
ll min_diff = LLONG_MAX;
void subsetGen(vector <ll> &curr,vector <ll> &v, int n, int index, ll sum)
{
if (!curr.empty())
{
ll sum_1 = accumulate(curr.begin(), curr.end(), 0);
ll diff = abs(2*sum_1 - sum);
min_diff = (diff<min_diff) ? diff : min_diff;
}
for (int i = index; i < v.size(); i++)
{
curr.push_back(v[i]);
subsetGen (curr, v, n, i+1, sum);
curr.pop_back(); // Backtracking
}
return;
}
int main()
{
int n;
ll sum = 0;
cin >> n;
vector <ll> v (n, 0);
for (int i=0; i<n; i++)
{
cin >> v[i];
sum += v[i];
}
vector <ll> curr;
subsetGen(curr,v,n,0,sum);
cout << min_diff;
return 0;
}
This was the Input I was checking for:
20
452747515 202201476 845758891 733204504 327861300 368456549 64252070 494676885 21095634 611030397 913689714 849191653 173901982 954566440 40404105 228316310 210730656 631709598 847867437 85805975
The correct answer is: 4881 (which the program using int gave)
But using long long is giving me: 4762526359 (which is the wrong answer).
I tested these code in online compilers to see if this was a problem with only my system, but encountered the same problem.

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);

Finding unique element in a long array gives segmentation fault?

I was given a problem to find unique elements in a array formed by using modulo operator over a long integers. So I have written code as:
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <set>
using namespace std;
int main(){
long n;
long s;
long p;
long q;
long temp;
long mod= pow(2, 31);
cin >> n >> s >> p >> q;
long array[n];
array[0] = (s % mod);
for(long i = 1; i < n; i++){
temp = array[i-1]*p+q;
array[i] = (temp % mod);
}
set<long> result(array, array + n);
cout << result.size() << endl;
return 0;
}
For smaller input the code runs perfectly fine. When it get tested for input:
100000000 1506922183 1236189611 306853238
It is giving the segmentation fault error.
Where I am going wrong?
Thanks.
long array[n]; is not Standard C++. In addition, given a sufficiently large n it will overrun your Automatic storage and make you have a very bad day. Consider using std::vector<long> array(n); instead.
The math:
long array[n]; with your input resolves to long array[100000000];
long is at least 4 bytes This means you are asking for a minimum of 100000000 * 4 bytes = 400000000 bytes = around 400 MB Automatic Storage.
Typical Automatic data store is a stack of approximately 1-10 MB.
On one side VLA is not legal C++ code, on another you do not need that array at all - you just waste memory:
cin >> n >> s >> p >> q;
set<long> result;
long value = 0;
for(long i = 0; i < n; i++){
value = ( i == 0 ? s : value * p + q ) % mod;
result.insert( value );
}
cout << result.size() << endl;
To speed up you code consider using std::unordered_set instead of std::set
How about this:
vector<long> v;
v.push_back(s % mod);
for (int i = 1; i < n; i++) {
long temp = v[i-1] * p + q;
v.push_back(temp % mod);
}
This way you will not have to define the size of the vector and let it handle it dynamically.

Summing Large Numbers

I have being doing some problems on the Project Euler website and have come across a problem. The Question asks,"Work out the first ten digits of the sum of the following one-hundred 50-digit numbers." I am guessing there is some mathematical way to solve this but I was just wondering how numbers this big are summed? I store the number as a string and convert each digit to a long but the number is so large that the sum does not work.
Is there a way to hold very large numbers as a variable (that is not a string)? I do not want the code to the problem as I want to solve that for myself.
I was just wondering how numbers this big are summed?
You can use an array:
long LargeNumber[5] = { < first_10_digits>, < next_10_digits>....< last_10_digits> };
Now you can calculate the sum of 2 large numbers:
long tempSum = 0;
int carry = 0;
long sum[5] = {0,0,0,0,0};
for(int i = 4; i >= 0; i--)
{
tempSum = largeNum1[i] + largeNum2[i] + carry; //sum of 10 digits
if( i == 0)
sum[i] = tempSum; //No carry in case of most significant digit
else
sum[i] = tempSum % 1000000000; //Extra digits to be 'carried over'
carry = tempSum/1000000000;
}
for( int i = 0; i < 5; i++ )
cout<<setw(10)<<setfill('0')<<sum[i]<<"\n"; //Pad with '0' on the left if needed
Is there a way to hold very large numbers as a variable (that is not a
string)?
There's no primitive for this, you can use any data structure (arrays/queues/linkedlist) and handle it suitably
I am guessing there is some mathematical way to solve this
Of course! But,
I do not want the code to the problem as I want to solve that for myself.
You may store the digits in an array. To save space and increase performance in the operations, store the digits of the number in base 10^9. so a number
182983198432847829347802092190
will be represented as the following in the array
arr[0]=2092190
arr[1]=78293478 arr[2]=19843284 arr[3]=182983
just for the sake of clarity, the number is represented as summation of arr[i]*(10^9i)
now start with i=0 and start adding the numbers the way you learnt as a kid.
I have done in java, Here I am taking to numbers N1 and N2, And I have create an array of size 1000. Lets take an example How to solve this, N1=12, N2=1234. For N1=12, temp=N1%10=2, Now add this digit with digit N2 from right to Left and store the result into array starting from i=0, similarly for rest digit of N1. The array will store the result but in reverse order. Have a looking on this link. Please check this link http://ideone.com/V5knEd
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception {
Scanner scan=new Scanner(System.in);
int A=scan.nextInt();
int B=scan.nextInt();
int [] array=new int[1000];
Arrays.fill(array,0);
int size=add(A,B,array);
for(int i=size-1;i>=0;i--){
System.out.print(array[i]);
}
}
public static int add(int A, int B, int [] array){
int carry=0;
int i=0;
while(A>0 || B>0){
int sum=A%10+B%10+carry+array[i];
array[i]=sum%10;
carry=sum/10;
A=A/10;
B=B/10;
i++;
}
while(carry>0){
array[i]=array[i]+carry%10;
carry=carry/10;
i++;
}
return i;
}
}
#include<iostream>
#include<fstream>
#include<sstream>
using namespace std;
struct grid{
int num[50];
};
int main()
{
struct grid obj[100];
char ch;
ifstream myfile ("numbers.txt");
if (myfile.is_open())
{
for(int r=0; r<100; r++)
{
for(int c=0; c<50; c++)
{
myfile >> ch;
obj[r].num[c] = ch - '0';
}
}
myfile.close();
int result[50],temp_sum = 0;
for (int c = 49; c>=0; c--)
{
for (int r=0; r<100; r++)
{
temp_sum += obj[r].num[c];
}
result[c] = temp_sum%10;
temp_sum = temp_sum/10;
}
string temp;
ostringstream convert;
convert << temp_sum;
temp = convert.str();
cout << temp_sum;
for(unsigned int count = 0; count < (10 - temp.length()); count++)
{
cout << result[count];
}
cout << endl;
}
return 0;
}
This the best way for your time and memory size :D
#include <iostream >
#include <climits >
using namespace std;
int main()
{
unsigned long long z;
cin >>z;
z=z*(z+1)/2;
C out << z;
return 0;
}