Limit on array size - c++

I wrote the following code in c++ which was supposed to print as well as calculate all the prime numbers till n.
The code is perfectly working for n<=10000 but is not working for n>=100000.
#include "iostream"
#include "vector"
using namespace std;
int main(){
int n,ans=0;
cin>>n;
vector <bool> v(n+1,true);
for(int i=2;i<=n;i++){
if(v[i]){
cout<<i<<endl;
ans++;
for(int j=i*i;j<=n;j+=i)
v[j]=false;
}
}
cout<<endl<<ans;
return 0;
}
Kindly state the reason.
Thank you.

In your inner look, j=i*i will overflow a 32-bit signed integer at around 46341. The easiest fix there is to use a long long for j and also cast i correctly before multiplication.
So, change the inner loop to
for (auto j = static_cast<long long>(i) * i; j <= n; j += i)
And that should be it.
As a side note, please don't #include standard headers with double quotes; prefer <vector> and <iostream>.
UPDATE: As a more robust way of doing the same thing (and still using roughly the same code,) I'd suggest the following:
#include <iostream>
#include <vector>
using namespace std;
int main(){
size_t n, ans = 0; // A) Switch to size_t, which can accommodate the largest
// size of a vector; if your number is larger, then we
// can't make an array for it...
cin >> n;
vector<bool> v (n, true); // B) Remove the chance of overflow; indices are
// now shifted by one
for(size_t i = 2; i <= n; i++) {
if (v[i - 1]) {
cout << i << endl;
ans++;
if (n / i >= i) { // C) Check for possibility of overflow in `i*i`
// D) Switch j to correct type
// E) Check if `j+=i` overflowed
for (size_t j = i * i; j <= n && j > i; j += i)
v[j - 1] = false;
}
}
}
cout << endl << ans;
return 0;
}
The really important changes are A, C, and D. The other two, B and E are needed for complete correctness, but they only matter when you have enough actual memory in your system to almost overflow size_t (otherwise, the ctor for vector would throw.) This is completely probably on 32-bit systems, but impossible on 64-bit builds for now.
Also note that A, B, and D are "essentially" free (perf-wise,) but C and E do have some impact on running time (although probably tiny; E is the more onerous.)

Related

How can I fix my code so I don't get a C6385 warning?

I'm having trouble with a C6385 warning in my code. I'm trying to see if two arrays will equal each other. The warning I keep getting is on the line where if(p[i] == inputGuess[j]). I have tried redoing these line but I keep getting the same warning. Does anyone know what I'm doing wrong. This is also my first time programming in C++.
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include "Game.h"
#include <iostream>
#include <iomanip>
using namespace std;
int* generateNumbers(int n, int m) {
// Intialize random number
srand(static_cast<unsigned int>(time(NULL)));
// Declare array size to generate random numbers based on what is between 1 to (m)
int* numbers = new int[n];
for (int i = 0; i < n; i++) {
numbers[i] = (rand() % m) +1;
cout << numbers[i]<< " " << endl;
}
return numbers;
}
void Game::guessingGame(int n, int m) {
int* p;
int sum = 0;
// Call the generateNumber function
generateNumbers(n, m);
// Declare array based on user guesses
inputGuess = new int[n];
p = generateNumbers(n,m);
for (int i = 0; i < n; i++) {
cin >> inputGuess[i];
}
// See if the user guesses and computers answers match up
for (int i = 0; i < n; i++) {
for (int j = 0; i < n; j++) {
if (p[i] == inputGuess[j]){ //Where I keep getting the C6385 Warning
sum++;
break;
}
}
}
}
The C6385 warning documentation states:
The readable extent of the buffer might be smaller than the index used
to read from it. Attempts to read data outside the valid range leads
to buffer overrun.
https://learn.microsoft.com/en-us/cpp/code-quality/c6385?view=msvc-160
Your second if statement compares i < n instead of j < n and since i is never modified inside it will run forever. This causes the warning since you’ll access memory out of bounds. Fix the comparison.

How to find the minimun of an array?

I was trying to solve this question
but codechef.com says the answer is wrong.
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int t, n, diff, mindiff;
cin >> t;
cin >> n;
int val[n];
while(t--)
{
mindiff = 1000000000;
for(int i = 0; i<n; i++)
{
cin >> val[i];
}
int a = 0;
for(a = 0; a<n ; a++)
{
for(int b=a+1; b<n ; b++)
{
diff = abs(val[a] - val[b]);
if(diff <= mindiff)
{
mindiff = diff;
}
}
}
cout << mindiff << endl;
}
return 0;
}
The results are as expected (for at least the tests I did) buts the website says its wrong.
There are a few things in your code that you should change:
Use std::vector<int> and not variable-length arrays (VLA's):
Reasons:
Variable length arrays are not standard C++. A std::vector is standard C++.
Variable length arrays may exhaust stack memory if the number of entries is large. A std::vector gets its memory from the heap, not the stack.
Variable length arrays suffer from the same problem as regular arrays -- going beyond the bounds of the array leads to undefined
behavior. A std::array has an at() function that can check boundary access when desired.
Use the maximum int to get the maximum integer value.
Instead of
mindif = 1000000000;
it should be:
#include <climits>
//...
int mindiff = std::numeric_limits<int>::max();
As to the solution you chose, the comments in the main section about the nested loop should be addressed.
Instead of a nested for loop, you should sort the data first. Thus finding the minimum value between two values is much easier and with less time complexity.
The program can look something like this (using the data provided at the link):
#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
int main()
{
int n = 5;
std::vector<int> val = {4, 9, 1, 32, 13};
int mindiff = std::numeric_limits<int>::max();
std::sort(val.begin(), val.end());
for(int a = 0; a < n-1 ; a++)
mindiff = std::min(val[a+1] - val[a], mindiff);
std::cout << mindiff;
}
Output:
3
To do this you can use a simple for():
// you already have an array called "arr" which contains some numbers.
int biggestNumber = 0;
for (int i = 0; i < arr.size(); i++) {
if (arr[i] > biggestNumber) {
biggestNumber = arr[i];
}
}
arr.size will get the array's length so that you can check every value from the position 0 to the last one which is arr.size() - 1 (because arrays are 0 based in c++).
Hope this helps.

Recursive Dynamic Programming Solution is Too Slow

I've been stuck for over an hour where I've had a correct solution to a dynamic programming problem, but it's too slow for some reason. I keep getting timeouts on test cases on hackerrank, even though I'm using C++ (I'd expect this kind of problem with Java).
Here is the Coin Change Problem
And here is my code for the problem:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
/*
N - The amount of change that should be created.
M - The number of elements in the C array.
C[] - The array of possible coins to use. Coins can be reused.
i - The index of the coin to begin with, as to not
repeat combinations already used.
*/
unsigned long long coinChangeCombinations(int N, int M, int C[], int i) {
unsigned long long combinations = 0;
for (; i < M; i++) {
int c = C[i];
if (N == c) {
combinations++;
} else if (N > c) {
combinations += coinChangeCombinations(N - c, M, C, i);
}
}
return combinations;
}
int main() {
unsigned long long N, M;
cin >> N;
cin >> M;
int C[M];
for (int i = 0; i < M; i++) {
int c;
cin >> c;
C[i] = c;
}
cout << coinChangeCombinations(N, M, C, 0) << endl;
return 0;
}
Most of the discussion is focussed around the iterative solution - is iterative always faster than recursive? In this case, I see no reason for the iterative solution to be faster than the recursive. Sure, recursion will take up more memory, but that's not the issue I'm running into here.

Mo's algorithm to compute "power" of array

Recently, I learned Mo's algorithm for the square-root decomposition of queries in order to speed up solutions to certain problems.
In order to practice implementation, I have been trying to solve D. Powerful array (a past contest problem on Codeforces) using this idea. The problem is as follows:
You have an array with integers .
Consider an arbitrary subarray . Define to be the number of occurrences of an integer in this subarray. The power of a subarray is defined as the sum of for all integers (note that there are only a positive number of terms for which this is not zero).
Answer queries. In each query, given two integers and , compute the power of .
It holds:
Using Mo's algorithm, I have written code that solves this problem offline in . I am certain that this problem can be solved using this algorithm and time complexity, as I have inspected the accepted code of others and they also use a similar algorithm.
My code, however, gets a time limit exceeded verdict.
Below is the code I have written:
#include <ios>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <utility>
#include <map>
int sqt;
long long int ans = 0;
long long int arr[200005] = {};
long long int cnt[1000005] = {};
long long int tans[200005] = {};
struct el
{
int l, r, in;
};
bool cmp(const el &x, const el &y)
{
if (x.l/sqt != y.l/sqt)
return x.l/sqt < y.l/sqt;
return x.r < y.r;
}
el qr[200005];
int main()
{
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
std::cout.tie(NULL);
int n, q, a, b;
std::cin >> n >> q;
sqt = sqrt((double)(n))+27;
for (int i = 0; i < n; i++)
std::cin >> arr[i];
for (int i = 0; i < q; i++)
{
std::cin >> a >> b;
a--; b--;
qr[i].l = a;
qr[i].r = b;
qr[i].in = i;
}
std::sort(qr, qr+q, cmp);
int li = 0; //left iterator
int ri = 0; //right iterator
ans = arr[0];
cnt[arr[0]]++;
for (int i = 0; i < q; i++)
{
while (li < qr[i].l)
{
ans -= cnt[arr[li]]*cnt[arr[li]]*arr[li];
cnt[arr[li]]--;
ans += cnt[arr[li]]*cnt[arr[li]]*arr[li];
li++;
}
while (li > qr[i].l)
{
li--;
ans -= cnt[arr[li]]*cnt[arr[li]]*arr[li];
cnt[arr[li]]++;
ans += cnt[arr[li]]*cnt[arr[li]]*arr[li];
}
while (ri < qr[i].r)
{
ri++;
ans -= cnt[arr[ri]]*cnt[arr[ri]]*arr[ri];
cnt[arr[ri]]++;
ans += cnt[arr[ri]]*cnt[arr[ri]]*arr[ri];
}
while (ri > qr[i].r)
{
ans -= cnt[arr[ri]]*cnt[arr[ri]]*arr[ri];
cnt[arr[ri]]--;
ans += cnt[arr[ri]]*cnt[arr[ri]]*arr[ri];
ri--;
}
tans[qr[i].in] = ans;
}
for (int i = 0; i < q; i++)
std::cout << tans[i] << '\n';
}
Can you suggest any non-asymptotic (or possibly even an asymptotic) improvement that can speed up the program enough to pass the time limit?
I have already tried the following things, to no avail:
Using a vector instead of an array.
Using two nested pairs instead of struct.
Using only one pair, and then using a map to try to recover the correct order of answers.
Adding some various constants to sqt (such as in the code above).
Overloading the < comparison operator within the struct el itself.
I feel like I'm missing something important, since the other codes I have inspected seem to pass the time limit with quite a bit of leeway (around half a second). Yet, they seem to be using the same algorithm as my code.
Any help would be highly appreciated!
You could strength-reduce
while (li < qr[i].l)
{
ans -= cnt[arr[li]]*cnt[arr[li]]*arr[li];
cnt[arr[li]]--;
ans += cnt[arr[li]]*cnt[arr[li]]*arr[li];
li++;
}
to
while (li < qr[i].l)
{
ans -= (2*cnt[arr[li]]-1)*arr[li];
cnt[arr[li]]--;
li++;
}
and likewise for the others.
You can modify the MO's sorting function comparator function cmp.
Your version:
bool cmp(const el &x, const el &y)
{
if (x.l/sqt != y.l/sqt)
return x.l/sqt < y.l/sqt;
return x.r < y.r;
}
Optimisation:
If the block is even, you can sort the R in descending order, and if the block is odd, you can sort the R in ascending order. This will minimise the movement of R pointer considerably when moving from one block to another.
My code:
bool cmp(const el &x, const el &y)
{
if (x.l/sqt != y.l/sqt)
return x.l/sqt < y.l/sqt;
return (x.l/sqt & 1) ? x.r < y.r : x.r > y.r; // avoids TLE
}

Strange output with large vectors

I was solving AMR10G problem on spoj. The problem is just about sorting and is trivial to implement with arrays. I'm a beginner in STL and just to get familiar with STL i was trying to solve it with using some vectors. The code runs fine with small sizes of vector but with large sizes( can be 20,000 in the problem) it prints all 0s. Here is my code.
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
using namespace std;
int main() {
int T;
cin>>T;
while(T--){
int N, k, i;
cin>>N >> k;
//***********************************************************
vector<int> ar(N);//problem seems to be here when N ~ 20000
//***********************************************************
for(i = 0; i<N; i++) scanf("%d",&ar[i]);
sort(ar.begin(),ar.end());
//calculate smallest difference
int small = ar[k-1] - ar[0];
for(i = k-1; i<N; i++){
int temp;
if( temp = ar[i] - ar[i-k+1] < small) small = temp;
}
cout<<small <<endl;//print smallest difference
}
return 0;
}
When I changed the type to array it ran perfectly fine. What is the problem with using vectors?
Your code has a lack of error checking:
Check that cin >> N >> k succeeded.
Check that each scanf succeeded.
Check k -1 is within range of the array bounds.
Any of those failures could cause your problem.
There is also a logic error on this line:
if( temp = ar[i] - ar[i-k+1] < small) small = temp;
The control expression is parsed as temp = (ar[i] - ar[i-k+1] < small), so this line will set small = 1 if ar[i] - ar[i-k+1] < small and do nothing otherwise. You probably meant (temp = ar[i] - ar[i-k+1]) < small).