简体   繁体   中英

I am new to C++ and I want to know how to optimise this code further

I am new to C++ and I have to optimise this code so that it gets executed within 1.5 secs for Input values upto 10^6. But this code takes 3.52 seconds for input 10^6 to get executed.

I had tried a lot and came up with this code.

#include <iostream>
#include <iostream>
#include <vector>
#include <bits/stdc++.h>
#include <iterator>
#include <utility>
#include <boost/multiprecision/cpp_int.hpp>

using boost::multiprecision::cpp_int;
using namespace std;

cpp_int gcd(cpp_int a, cpp_int b)
{
    // Everything divides 0
    if (a == 0)
        return b;
    if (b == 0)
        return a;

    // base case
    if (a == b)
        return a;

    // a is greater
    if (a > b)
        return gcd(a - b, b);
    return gcd(a, b - a);
}

int main()
{

    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cpp_int t, ans;
    std::cin >> t;
    while (t-- > 0) {
        cpp_int k;
        std::cin >> k;
        cpp_int limit = (2 * k) + 1;
        ans = 0;

        vector<cpp_int> g1;

        for (int i = 1; i <= limit; ++i)
            g1.push_back(k + (i * i));

        for (int i = 0; i <= (2 * k) - 1; ++i) {
            ans += gcd(g1[i], g1[i + 1]);
        }

        std::cout << ans << std::endl;
    }
    return 0;
}

Constraints --> 1 ≤ t ≤ 10^6 & 1 ≤ k ≤ 10^6

  • std::endl is better to be replaced with '\n' . std::endl flushes output stream and it is not a cheap operation, because it ignores all the advantages of buffered output.
  • g1.reserve(MAX_G1_SIZE) after g1 initialization. It looks like your g1 vector is big enough at the end of the program. a vector is a dynamic array, which means that as soon as its capacity becomes insufficient, a larger piece of memory is allocated in the heap and existing elements are copied there. This operation has linear complexity but is rarely performed. The solution is to first tell the vector what size to reserve with the command g1.reserve(MAX_G1_SIZE) ( MAX_G1_SIZE is maximal g1 size after program evaluation. For example, we can put MAX_G1_SIZE = t ).
  • Make gcd not recursive. This usually doesn't speed things up much, but it may help.

You do not reserve memory in advance, so you suffer from continuous re-allocations, especially as you have a locally created std::vector .

Keeping the vector outside of the loop allows to re-use previously allocated memory (you'd simply clear the vector). However it is pretty simple to get along without an additional vector at all:

cpp_int n = k + 1;
for (int i = 2; i <= limit; ++i)
{
    cpp_int m = k + i * i; // if multiplication is costly: = m + i << 1 - 1
    ans += gcd(n, m);
    n = m;
}

Not sure how complex modulo operator is with boost's multiprecision library, but I'd assume you get further improvement by using that one instead of subtraction:

return b == 0 ? a : gcd(b, a % b);

Modulo reaches quicker the gcd, additionally you spare some if's (if a is 0 or smaller than b on first call, you get one additional recursion that only swaps the two values).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM