I was given this challenge in a programming "class". Eventually I decided to go for the "Binary Indexed Trees" solution, as data structures are a thing I'd like to know more about. Implementing BIT was somewhat straight forward, things after that - not so much. I ran into "Fatal Signal 11" when uploading the solution to the server, which, from what I've read, is somewhat similar to a Null pointer exception. Couldn't figure out the problem, decided to check out other solutions with BIT but stumbled upon the same problem.
#include<iostream>
using namespace std;
/* <BLACK MAGIC COPIED FROM geeksforgeeks.org> */
int getSum(int BITree[], int index){
int sum = 0;
while (index > 0){
sum += BITree[index];
index -= index & (-index);
}
return sum;
}
void updateBIT(int BITree[], int n, int index, int val){
while (index <= n){
BITree[index] += val;
index += index & (-index);
}
}
/* <BLACK MAGIC COPIED FROM geeksforgeeks.org> */
int Count(int arr[], int x){
int sum = 0;
int biggest = 0;
for (int i=0; i<x; i++) {
if (biggest < arr[i]) biggest = arr[i];
}
int bit[biggest+1];
for (int i=1; i<=biggest; i++) bit[i] = 0;
for (int i=x-1; i>=0; i--)
{
sum += getSum(bit, arr[i]-1);
updateBIT(bit, biggest, arr[i], 1);
}
return sum;
}
int main(){
int x;
cin >> x;
int *arr = new int[x];
for (int temp = 0; temp < x; temp++) cin >> arr[temp];
/*sizeof(arr) / sizeof(arr[0]); <-- someone suggested this,
but it doesn't change anything from what I can tell*/
cout << Count(arr,x);
delete [] arr;
return 0;
}
I am quite stumped on this. It could be just some simple thing I'm missing, but I really don't know. Any help is much appreciated!
You have condition that every number lies between 1 and 1018. So, your biggest number can be 1018. This is too much for the following line:
int bit[biggest+1];
Related
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.
#include <iostream>
using namespace std;
int main()
{
int n;
n=4;
int arr[n]={1,2,3,8};
int sum;
sum=5;
int curr=0;
cin>>sum;
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
curr+=arr[j];
if(curr==sum){
cout<<i;
}
cout<<curr<<endl;
}
}
}
For the given question I need to find the starting and ending index of such a subarray. I have tried the above code but am not able to get the right output. Please guide me.
I think your code only needs some minor modifications. You should add
some code to handle the case where your running sum is greater than the target sum, and you should also re-initialize your running sum correctly.
There may be some efficient solution that is faster than O(n^2), which I am not aware of yet. If someone knows of a solution with a better time complexity, please share with us.
Below is a simple algorithm that has the time complexity of O(n^2). (It may not have the most efficient time complexity for this problem).
This function prints out the 2 indices of the array. The sum of all elements between these 2 indices inclusively will equal the target sum.
void Print_Index_of_2_Elements(int array[], int total_element, int target)
{
// Use Brute force . Time complexity = O(n^2)
for (int i = 0; i < total_element; i++)
{
int running_sum = array[i];
// Second for loop
for (int j = (i + 1) ; j < total_element; j++)
{
if (running_sum == target)
{
cout << "Two indices are: " << i << " and " << j;
return; // Found Answer. Exit.
}
else if ( running_sum > target )
break;
else // running_sum < target
running_sum += array[j];
}
}
cout << " Sorry - no answer was found for the target sum.";
}
If you are someone that is a beginner in subarrays or arrays for the case. Then this code is for you:
#include <iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int arr[n];
for(int i=0;i<n;i++){
cin>>arr[i];
}
int sum;
cin>>sum;
int curr=0;
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
if(curr==sum){
cout<<i+1<<" "<<j;
return 0;
}
else if (curr>sum){
curr=0;
}
else if(curr<sum){
curr+=arr[j];
}
}
}
return 0;
}
If you have any doubts regarding this, feel free to comment and let me know.
So i', trying to solve a task.
a already have code, but system outs, "stack overflow"
i'm new in c++ and my english isn't good so i'm sorry for misunderstanding =)
#include <iostream>
using namespace std;
int main (){
int n;
int x;
int k = 0; // счетчик для рабочего массива
int a [200000];
scanf("%d\n",&n);
for (int i = 0; i< n; ++i){
std::cin >> x;
if (x > 0){
k++;
a[k] = x;
}else if(x == 0){
for (int q = 1; q <= k; ++q){ // копирование
a[k+q] = a[q];
}
k *= 2;
}else{
printf("%d %d\n",a[k],k);
k--;
}
}
system("pause");
}
looks like algorithm works correctly, but only problem is stack. thanks a lot!
Root Cause:
As you guessed correctly, the stack is limited and seems your allocation is large enough to be catered through it. This is not an language syntax error so it does not warrant a compilation error but it results in a run time exception thus causing a crash.
Solution 1:
You can make the array global, the allocation of an global array is not on stack so it should work fine for you:
int a [200000];
int main()
{
.....
}
Solution 2:
You could use a std::vector
Solution 3:
You can use dynamic allocation through new.
Statement int a [200000]; attempts to allocate more memory on the stack than will fit, which caused stack overflow. Some people recommend that arrays larger than a few kilobytes should be allocated dynamically instead of as a local variable. Please refer to wikipedia: http://en.wikipedia.org/wiki/Stack_overflow#Very_large_stack_variables
3 changes I can see.
1 - allocating on the stack more than the stack can handle.
2 - k should always pointing to the next free space so you need to update than increase it.
3 - the index are starting from "0" both for the "q" for.
Fixed code:
#include <iostream>
using namespace std;
int a [200000];
int main (){
int n;
int x;
int k = 0; // счетчик для рабочего массива
scanf("%d\n",&n);
for (int i = 0; i< n; ++i){
std::cin >> x;
if (x > 0)
{
a[k] = x;
k++; //<< change 1
}
else if (x == 0)
{
for (int q = 0; q <= k; ++q) //<<change 2
{ // копирование
a[k+q] = a[q];
}
k *= 2;
}
else
{
printf("%d %d\n",a[k],k);
k--;
}
}
system("pause");
}
#include <cstdio>
#include <ctime>
int populate_primes(int array[])
{
const int max = 1000000;
char numbers[max+1];
int count=1;
array[0]=2;
for(int i=max;i>0;i-=2)numbers[i]=0;
for(int i=max-1;i>0;i-=2)numbers[i]=1;
int i;
for(i=3;i*i<=max;i+=2){
if(numbers[i]){
for(int j=i*i;j<max+1;j+=i)numbers[j]=0; array[count++]=i;
}
}
int limit = max/2;
for(;i<limit;i++) if(numbers[i])array[count++]=i;
return count;
}
int factorize(int number,int array[])
{
int i=0,factor=1;
while(number>0){
if(number%array[i]==0){
factor++;
while(number%array[i]==0)number/=array[i];
}
i++;
}
printf("%d\n",factor);
return factor;
}
int main()
{
int primes[42000];
const int max = 1000000;
int factors[max+1];
clock_t start = clock();
int size = populate_primes(primes);
factorize(1000,primes);
printf("Execution time:\t%lf\n",(double)(clock()-start)/CLOCKS_PER_SEC);
return 0;
}
I am trying to find the no. of factors using simple algo. The populate primes part is running okay , but the factorize part does not execute and gives the floating point exception error.
Please see the code and tell my mistake.
In your factorize method you access array[0], because the initial value of i is 0.
This array is the primes array which is populated by populate_primes. But populates prime doesn't write to primes[0], since the initial value of count is 1.
Thus the first element is not initialized and you probably get a div by 0 error.
You need to pass the size which you got from populate to factorize.
factorize(int number, int array[], int size);
problem is your array[] is not fully loaded, it is loaded only till size variable. So you may want to check for that.
Also the logic inside factorize is wrong. You need to check (number > 1) rather than (number >0).
Try with the function below to see some problems:
#define MAX_PRIMES 42000
int factorize(int number,int array[])
{
int i=0,factor=1;
for (i=0; number>0 && i< MAX_PRIMES; i++){
if (array[i] == 0 || array[i] == 1) {
printf("Error: array[%d] = %d\n", i, array[i]);
} else {
if(number%array[i]==0){
factor++;
while(number%array[i]==0 && number>0) {
printf("%d %d\n", number, array[i]);
number/=array[i];
}
}
}
}
printf("%d\n",factor);
return factor;
}
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 ;)