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.
Related
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.)
When i run the source code on sample cases of their example it runs fine but when I submit the question It says runtime error.
Here is my Source code and link of the question.
Question link - https://www.codechef.com/SEPT21C/submit/MNDIGSM2
Below is the code.
#include <iostream>
#include <vector>
// #include <bits/stdc++.h>
using namespace std;
// #define fast ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int converter(int n , int b){
vector<int> vec;
int sum = 0;
while(n>0){
vec.push_back(n%b);
n = n / b;
}
int vecSize = vec.size();
for(int i = 0;i<vecSize;i++){
// cout<<
sum = sum + vec[i];
}
return sum;
}
int minVal(vector<int> arr , int len){
int min = arr[0], c = 0;
// if(arr)
for(int i = 1 ; i< len;i++){
if (arr[i] < min){
min = arr[i];
c = i;
}
}
return c;
}
int main() {
// your code goes here
// fast;
int test;
cin>>test;
while(test--){
int n ,r;
cin>>n>>r;
int l = 2;
// ll copy = l;
int arSize = (r-2)+1;
vector<int> arr(arSize);
for(int i = 0;i< arSize ;i++){
arr[i] = converter(n,l);
l++;
}
int tobe = minVal(arr , arSize);
cout<<tobe + 2<<endl;
}
return 0;
}
Maybe I do not understand the question fully. There is not enough information available.
It could be that the program slows down because the usage of the std::vector. First you calculate, then store the values and then iterate again over all values.
This is not necessary. You can do all calculations inline without the need for additional storage.
And, additionally, all these "contest" questions do not have the intention, to improve your programming skills.
Basically the language doesn't matter. The important thing is the algorithm. They want you to find a "good" algorithm.
Bruteforcing is nearly never a feasible solution. If you read about big numbers like 10^12, then you know already in advance that you will get a TLE with the brute force solution.
Regarding this horrible and non compliant C++ slang that is used on this "competetion" sides, please note that this is nearly never necessary. You have no time contraints to submit a solution. So, you could use also real C++ code.
Anyway. I corrected your code and added meaningful varibale names, comments and formatting. So, logically, the approach is the same, but it is readable.
Of course it may fail as well, because it is still brute forcing . . .
#include <iostream>
#include <limits>
constexpr unsigned long long BaseStart = 2ull;
int main() {
// Get number of test cases
unsigned int numberOfTestCases{};
std::cin >> numberOfTestCases;
// Work on all test cases
for (unsigned int testCase{}; testCase < numberOfTestCases; ++testCase) {
// Get the value to check and the upper limit for the base
unsigned long long valueToCheck{}, upperLimitBase{};
std::cin >> valueToCheck >> upperLimitBase;
// Here we will store the minimum sum to check
unsigned long long minimumsumOfDigits{std::numeric_limits<unsigned long long>::max()};
// Here we will store the result
unsigned long long minimumBase{};
for (unsigned long long base{BaseStart}; base <= upperLimitBase; ++base) {
// And this will be the running sumOfDigits
unsigned long long runningSumOfDigits{};
// get the digits of the value and calculate the running sum
unsigned long long value{valueToCheck};
while (value > 0) {
// Get digits via modulo division and add up
runningSumOfDigits += value % base;
value /= base;
}
// Get current minimum
if (runningSumOfDigits < minimumsumOfDigits) {
minimumsumOfDigits = runningSumOfDigits;
minimumBase = base;
}
}
std::cout << minimumBase << '\n';
}
return 0;
}
This code can of course be optimized further, but for this I would need more information . . .
I was doing a problem named Sam and sub-strings on hackerrank which you can look by clicking on the corresponding link.
Here is my code. I am sure that the logic of my program is correct as it works for smaller values (and also the sample test cases). The problem is with modulus and I am not able to get how to use modulus in this program correctly. Can anyone please help me (if possible, please tell when/where to use modulus in the program without editing the rest of my program)?
My submission gives correct results for testcases 0,1,2,3,12 and incorrect results for the rest.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
long long int n;
cin >> n;
vector<long long int> v1;
while (n!=0){
v1.push_back(n%10);
n=n/10;
}
long long int x=1,s1=0,sum=0;
for (long long int i=v1.size()-1;i>=0;i--){
s1+=x*v1[i];
x++;
sum=(sum+(s1*(long long int)pow(10,i))%1000000007)%1000000007;
}
cout << sum << endl;
return 0;
}
I suggest you treat the number as text when playing with digits.
int main()
{
std::string number_as_text;
std::cin >> number_as_text;
long long sum = 0;
const std::string::size_type length = number_as_text.length();
for (unsigned int index = 0; index < length; ++index)
{
long long s1 = (number_as_text[index] - '0') * (index + 1);
sum = sum * 10 + s1;
}
return 0;
}
You'll have to figure out where to put the mod 1000000007 in your program, if you need to.
Also, I recommend placing error handling in the code, especially when reading in the number. The function std::isdigit looks helpful.
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
}
I have been working on this for 24 hours now, trying to optimize it. The question is how to find the number of trailing zeroes in factorial of a number in range of 10000000 and 10 million test cases in about 8 secs.
The code is as follows:
#include<iostream>
using namespace std;
int count5(int a){
int b=0;
for(int i=a;i>0;i=i/5){
if(i%15625==0){
b=b+6;
i=i/15625;
}
if(i%3125==0){
b=b+5;
i=i/3125;
}
if(i%625==0){
b=b+4;
i=i/625;
}
if(i%125==0){
b=b+3;
i=i/125;
}
if(i%25==0){
b=b+2;
i=i/25;
}
if(i%5==0){
b++;
}
else
break;
}
return b;
}
int main(){
int l;
int n=0;
cin>>l; //no of test cases taken as input
int *T = new int[l];
for(int i=0;i<l;i++)
cin>>T[i]; //nos taken as input for the same no of test cases
for(int i=0;i<l;i++){
n=0;
for(int j=5;j<=T[i];j=j+5){
n+=count5(j); //no of trailing zeroes calculted
}
cout<<n<<endl; //no for each trialing zero printed
}
delete []T;
}
Please help me by suggesting a new approach, or suggesting some modifications to this one.
Use the following theorem:
If p is a prime, then the highest
power of p which divides n! (n
factorial) is [n/p] + [n/p^2] +
[n/p^3] + ... + [n/p^k], where k is
the largest power of p <= n, and [x] is the integral part of x.
Reference: PlanetMath
The optimal solution runs in O(log N) time, where N is the number you want to find the zeroes for. Use this formula:
Zeroes(N!) = N / 5 + N / 25 + N / 125 + ... + N / 5^k, until a division becomes 0. You can read more on wikipedia.
So for example, in C this would be:
int Zeroes(int N)
{
int ret = 0;
while ( N )
{
ret += N / 5;
N /= 5;
}
return ret;
}
This will run in 8 secs on a sufficiently fast computer. You can probably speed it up by using lookup tables, although I'm not sure how much memory you have available.
Here's another suggestion: don't store the numbers, you don't need them! Calculate the number of zeroes for each number when you read it.
If this is for an online judge, in my experience online judges exaggerate time limits on problems, so you will have to resort to ugly hacks even if you have the right algorithm. One such ugly hack is to not use functions such as cin and scanf, but instead use fread to read a bunch of data at once in a char array, then parse that data (DON'T use sscanf or stringstreams though) and get the numbers out of it. Ugly, but a lot faster usually.
This question is from codechef.
http://www.codechef.com/problems/FCTRL
How about this solution:
#include <stdio.h>
int a[] = {5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, 48828125, 244140625};
int main()
{
int i, j, l, n, ret = 0, z;
scanf("%d", &z);
for(i = 0; i < z; i++)
{
ret = 0;
scanf("%d", &n);
for(j = 0; j < 12; j++)
{
l = n / a[j];
if(l <= 0)
break;
ret += l;
}
printf("%d\n", ret);
}
return 0;
}
Any optimizations???
Knows this is over 2 years old but here's my code for future reference:
#include <cmath>
#include <cstdio>
inline int read()
{
char temp;
int x=0;
temp=getchar_unlocked();
while(temp<48)temp=getchar_unlocked();
x+=(temp-'0');
temp=getchar_unlocked();
while(temp>=48)
{
x=x*10;
x+=(temp-'0');
temp=getchar_unlocked();
}
return x;
}
int main()
{
int T,x,z;
int pows[]={5,25,125,625,3125,15625,78125,390625,1953125,9765625,48828125,244140625};
T=read();
for(int i=0;i<T;i++)
{
x=read();
z=0;
for(int j=0;j<12 && pows[j]<=x;j++)
z+=x/pows[j];
printf("%d\n",z);
}
return 0;
}
It ran in 0.13s
Here is my accepted solution. Its score is 1.51s, 2.6M. Not the best, but maybe it can help you.
#include <iostream>
using namespace std;
void calculateTrailingZerosOfFactoriel(int testNumber)
{
int numberOfZeros = 0;
while (true)
{
testNumber = testNumber / 5;
if (testNumber > 0)
numberOfZeros += testNumber;
else
break;
}
cout << numberOfZeros << endl;
}
int main()
{
//cout << "Enter number of tests: " << endl;
int t;
cin >> t;
for (int i = 0; i < t; i++)
{
int testNumber;
cin >> testNumber;
calculateTrailingZerosOfFactoriel(testNumber);
}
return 0;
}
#include <cstdio>
int main(void) {
long long int t, n, s, i, j;
scanf("%lld", &t);
while (t--) {
i=1; s=0; j=5;
scanf("%lld", &n);
while (i != 0) {
i = n / j;
s = s + i * (2*j + (i-1) * j) / 2;
j = j * 5;
}
printf("%lld\n", s);
}
return 0;
}
You clearly already know the correct algorithm. The bottleneck in your code is the use of cin/cout. When dealing with very large input, cin is extremely slow compared to scanf.
scanf is also slower than direct methods of reading input such as fread, but using scanf is sufficient for almost all problems on online judges.
This is detailed in the Codechef FAQ, which is probably worth reading first ;)