Optimization of C++ code - c++

This is my solution to Spoj 11373. Coke madness
#include <cstdio>
int main(){
int T; scanf("%d",&T);
for(int j = 1; j <= T; j++){
int n;
scanf("%d",&n);
long long sum = 0, small = 0;
int t;
for(int i = 0; i < n; i++) {
scanf("%d",&t);
sum += t;
if( sum < small) small = sum;
}
printf("Scenario #%d: %lld\n", j, -1*small+1);
}
}
The problem is simple. This solution takes 0.12 seconds on Spoj, though there are 0.01 second solutions. I am curious what optimizations may be done to this code to get faster. I thought -1*small+1 may be got using bit-wise operations but didn't find how. Also I can't get rid of long long since sum may exceed int.

You're making way too many I/O calls. Read the whole file at once, and then parse it, then create your output, and then write it all at once.

Related

Can't seem to find the error - memory access violation

I'm trying to solve a problem on france IOI about a card game (named "Reussite" on level 4) that requires outputting every odd number, however I keep getting (0xC0000005) code if my input is bigger than about 48000 and I can't seem to find the error. Help!
here's my code:
#include<bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
int n;cin>>n;vector<int> arr(n+1);
for (int i = 2; i < n+1; ++i) {
int m = i;
//error is in this while loop
while (i*m<=n){arr[i*m]=1;m++;}
}
for (int i = 0; i < n+1; ++i) {
if (arr[i]==0) printf("%d \n",i);
}
}
When the value n is at least 46341, its square no longer fits into a 32-bit signed integer, so the expression i*m results in an integer overflow.
You might want to cast the values to long long, like while ((long long)i*m<=n) or while (i*1LL*m<=n), or change your code otherwise.

Why is std::pow(int, int) way faster than for loop with integer values?

Me and my friend wrote a program which calculates the polynomial:
P = abn + a2bn-1 + a3bn-2 + ... anb
He used the C++ std::pow(int, int) function, whereas I used two for loops as I've been taught that for loops with integers are faster than the std::pow(int, int) function or in worst case the speed is gonna be almost the same!
His code:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int a = 1,b = 1,n = 100000;
long long P = 0;
for(int i = 1, j = n; i <= n; i++, j--)
{
P += pow(a,i) * pow(b,j);
}
cout << P;
return 0;
}
The program returns 100000 as expected with execution time: 0.048 s and 0.049 s when ran second time
However when I run my code:
#include <iostream>
using namespace std;
int main()
{
int a = 1,b = 1,n = 100000;
long long P = 0;
for(int i = 1, j = n; i <= n; i++, j--)
{
int c = a, d = b;
for (int k = 1; k < i; ++k) {
c *= a;
}
for (int k = 1; k < j; ++k) {
d *= b;
}
P += c * d;
}
cout << P;
return 0;
}
The program returns again the expected 100000 but with execution time: 17.039 s and 17.117 s when ran second time.
My question is, as I have always been taught by people and I have read in articles and tutorials that the std::pow(int, int) is either gonna be slower than a for loop with integers or the speed is gonna be almost equal, why is the execution time having such a big difference if we up the number to 1000000 it's gonna even take a couple of minutes before my code executes, whereas the pow(int, int) function code executes within seconds.
It completely depends on the quality of std::pow implementation, and the optimization capability of your compiler
For example some standard libraries calculate pow(x, y) as exp(log(x)*y) even for integer exponents, therefor it may be inaccurate and slow, resulting in issues like these
Why does pow(5,2) become 24?
Why pow(10,5) = 9,999 in C++
But some better pow implementations check if the exponent is integer to use a better algorithm. They also use exponentiating by squaring so they'll be magnitudes faster than your linear multiplication like your for loop. For example for b100000 they need only 17 loops instead of 100000
If a compiler is smart enough to recognize your loop as to calculate power, it may convert to std::pow completely. But probably it's not your case so std::pow is still faster. If you write your pow(int, int) function that uses exponentiating by squaring then it may likely be faster than std::pow

getting no result in terminal window

I have just started coding in C++ and I am using codeblocks. My build log is giving me 0 errors and 0 warning but I do not know why when I run it, it is giving me no result in the terminal.
Terminal Window Result:
Process returned -1073741571 (0xC00000FD) execution time : 1.252 s
Press any key to continue.
my code:
#include <iostream>
#include<math.h>
using namespace std;
int main() {
int n;
cin>>n;
int a[n];
for(int i = 0; i <n ; i++){
cin>>a[i];
}
const int N = pow(10, 6);
int idx[N];
for(int i = 0; i< N; i++){
idx[i] = -1;
}
int minidx = INT_MAX;
for(int i = 0; i<n; i++){
if(idx[a[i]] != -1){
minidx = min(minidx, idx[a[i]]);
}
else{
idx[a[i]] = i;
}
}
if (minidx == INT_MAX){
cout<<"-1"<<endl;
}
else{
cout<<minidx+1<<endl;
}
return 0;
}
Please help me in finding my mistake in the code.
This:
int n;
std::cin >> n;
int a [n];
for (int i = 0; i < n ; i++) {
std::cin >> a [i];
}
is bad practice. Don't use VLAs whose size you don't know at compile time. Instead, if I guess correctly that this is some Competitive Programming problem, you'll probably know what the max size will be as stated in the problem. So, do it this way instead:
int n;
std::cin >> n;
constexpr int max_size = 1000000;
int a [max_size];
for (int i = 0; i < n; i++) {
std::cin >> a [i];
}
However, even doing it this way will crash your program anyway. This is simply because of stack overflow when you declare an array that size inside a function. For slightly smaller sizes however, that would be okay. Just don't use VLAs the way you're using them.
One solution is to use a standard container like std::vector as the allocation takes place on the heap. Note that using std::array will crash too as the allocation is not on the heap.
Another solution is to make your array a global. This way you can increase to sizes well over 1e6. Not really recommended though.
In your code above, irrespective of what the size n for array a is (even if it's a fairly small size to fit on the stack), your code will definitely crash when you declare the array idx [1000000]. Reason is the same, stack overflow.
Also, please post indented code and use good indentation practices.

Simple C++ Summing Program

This is my first time using C++ and I am writing a small program to sum up to ten numbers (doubles) that will be entered in the command prompt.
I have written the following code and I cannot figure out why it will not produce the desired result.
int main()
{
double num[10];
double sum = 0;
int i;
int n = 10;
while (scanf_s("%lf", &num) != EOF)
{
for (i = 0; i < n; ++i)
{
scanf_s("%lf", &num);
sum = sum + num[i];
}
}
cout << sum;
system("pause");
return 0;
}
The data entry is terminated with a control D.
In my eyes it should run fine but it doesn't. Could someone please give me some pointers for solving this, I don't just want to be told the correct way I would rather learn it myself.
The problem is that &num is the address of the array. SO you read your value always in num[0] meaning that num[i]is random in most of the cases.
Try to change your loop:
for (i = 0; i < n && (cin>>num[i]); ++i)
{
sum = sum + num[i];
}

2D Vector Optimization

This is only a compact test case but I have a vector of doubles and I want to populate a square matrix (2D vector) of all pairwise differences. When compiled with -O3 optimization, this takes about 1.96 seconds on my computer (computed only from the nested double for-loop).
#include <vector>
using namespace std;
int main(){
vector<double> a;
vector<vector<double> > b;
unsigned int i, j;
unsigned int n;
double d;
n=10000; //In practice, this value is MUCH bigger
a.resize(n);
for (i=0; i< n; i++){
a[i]=static_cast<double>(i);
}
b.resize(n);
for (i=0; i< n; i++){
b[i].resize(n);
b[i][i]=0.0; //Zero diagonal
}
for (i=0; i< n; i++){
for (j=i+1; j< n; j++){
d=a[i]-a[j];
//Commenting out the next two lines makes the code significantly faster
b[i][j]=d;
b[j][i]=d;
}
}
return 0;
}
However, when I comment out the two lines:
b[i][j]=d;
b[j][i]=d;
The program completes in about 0.000003 seconds (computed only from the nested double for-loop)! I really didn't expect these two lines to be the rate-limiting-step. I've been staring at this code for a while and I'm out of ideas. Can anybody please offer any suggestions as to how I could optimize this simple piece of code so that the time can be significantly reduced?
When you comment out those two lines, all that's left in the nested loop is to keep computing d and then throwing away the result. Since this can't have any effect on the behaviour of the program, the compiler will just optimize out the nested loop. That's why the program finishes almost instantaneously.
In fact, I confirmed this by compiling the code twice with g++ -O3, once with only the d=a[i]-a[j] statement in the nested loop, and once with the nested loop deleted entirely. The code emitted was identical.
Nevertheless, your code is currently slower than it has to be, because it's missing the cache. When you access a two-dimensional array in a nested loop like this, you should always arrange for the iteration to be continuous through memory if possible. This means that the second index should be the one that's varying faster. The access to b[j][i] is violating this rule and missing the cache. So let's rewrite.
Before:
for (i=0; i< n; i++){
for (j=i+1; j< n; j++){
d=a[i]-a[j];
b[i][j]=d;
b[j][i]=d;
}
}
Timing:
real 0m1.026s
user 0m0.824s
sys 0m0.196s
After:
for (i = 0; i < n; i++) {
for (j = 0; j < i; j++) {
b[i][j] = a[j] - a[i];
}
for (j = i+1; j < n; j++) {
b[i][j] = a[i] - a[j];
}
}
Timing:
real 0m0.335s
user 0m0.164s
sys 0m0.164s