Newton's binomial - doesn't work for bigger numbers - c++

I wrote a program which is supposed to print the value of Newton's binomial.
number - number of tests, t[i][0] - n, t[i][1] - k. It seems to be ok for small numbers n and k, but when I want to type bigger numbers it prints 0, 1 or small, negative integer. Basically I used long intead of int so it should work with bigger numbers. Could you explain why is that?
#include <iostream>
long fact(int x);
using namespace std;
int main()
{
int number;
cin>>number;
int t[number][2];
for(int i=0; i<number; i++)
{
cin>>t[i][0];
cin>>t[i][1];
if (t[i][0]<t[i][1]) return 0;
}
for(int i=0; i<number; i++)
{
cout<<fact(t[i][0])/(fact(t[i][0]-t[i][1])*fact(t[i][1]))<<endl;
}
return 0;
}
long fact(int x)
{
long factt=1;
for(int i=1; i<=x; i++)
{
factt=factt*i;
}
return factt;
}
#edit
Thanks for advice. I tried implementing this but it doesn't compute the binomial well. It prints 11 for n=4 and k=2. May you have a look at this?
#include <iostream>
long fact(int n, int k);
using namespace std;
int main()
{
int number;
cin>>number;
int t[number][2];
for(int i=0; i<number; i++)
{
cin>>t[i][0];
cin>>t[i][1];
if (t[i][0]<t[i][1]) return 0;
}
for(int i=0; i<number; i++)
{
cout<<fact(t[i][0],t[i][1])<<endl;
}
return 0;
}
long fact(int n, int k)
{
if(n==0 || n==k)
return 1;
else if(n>k)
return fact(n-1,k-1)+fact(n-1, k);
else
return 0;
}

Factorial grows really fast and even unsigned 64-bit integers overflow n! for n>20. The overflow free way to implement the binomial coefficient is to use this recursive definition:
binom(n, k) = binom(n-1, k-1) + binom(n-1, k)
This ensures that you get an overflow only when binom(n,k) is too large to fit in your integral type's size.

On Linux 32bit long is the same as int and fits into 32bit. On Linux 64bit long is 64bit long.
On Windows both 32bit and 64bit long is 32bits entity
You have to use long long to guaranteed to use 64bit, though it might be not enough to overcome overflow. Use recursive formula for binominal, if possible

Related

Codechef rejection (factorial of a number)

Why is codechef rejecting this solution even though it's giving desirable outputs on codechef code runner itself? (Factorial of a number)
#include <iostream>
using namespace std;
int main() {
int t;
cin>>t;
int n;
int fact=1;
for(int i=0; i<t;i++){
cin>>n;
for(int i=1; i<=n; i++){
fact=fact*i;
}cout<<fact;
cout<<endl;
fact=1;
}
return 0;
}
As you are storing the result of factorial in int variable, which has a max limit of 2147483647, so for numbers larger than this, factorial will not be computed correctly.
Try using other data types which can have max higher limits. https://learn.microsoft.com/en-us/cpp/c-language/cpp-integer-limits?view=msvc-160

Algorithm crashing

int function(int A[], int n)
{
int i = 0;
int sum = 0;
int amount = 0;
while(i<n) {
if(A[i] > 0) {
sum=sum+A[i];
amount++;
}
else {
i++;
}
}
while(!(i<n)) {
if(ile>0){
return sum/amount;
} else {
return 0;
}
}
}
I am generating random array of numbers between 0-10 , Im trying to use this with this algorithm, but all the time im getting result 6422260. Can someone tell me how should I approach this?
int n;
cin >> n;
int arr[n];
srand(time(NULL));
for (int i = 0; i < 10; i++)
{
arr[i] = rand() % 10;
}
function(arr, n);
Here is a solution to your problem:
#include <random>
#include <iostream>
void fill(int arr[]);
int random(int from, int to);
using namespace std;
int main(void)
{
int arr[10];
fill(arr);
for(int i = 0; i<10; i++)
printf("%d ", arr[i]);
return 0;
}
void fill(int arr[]){
for(int i=0;i<(*(&arr + 1) - arr);i++){
arr[i] = random(0, 10);//adjust accordngly
}
}
int random(int from, int to){
std::random_device dev;
std::mt19937 rng(dev());
std::uniform_int_distribution<std::mt19937::result_type> dist6(from, to); // distribution in range [from, to]
return dist6(rng);
}
Your problem is you are not generating random numbers your algorithm is generating the same set of numbers! You need a logic to generate random number. Usually they are generated from system time ...
Attribution : https://stackoverflow.com/a/13445752/14911094
#alkantra, your problem is not generating random numbers. Basically, you are asking your question wrong. If required, it should be separated:
What's this code doing?
How to generate a random sequence?
The algorithm you are trying to achieve is for calculating arithmetic mean (or simply average). If you remember the formula for calculating arithmetic mean you learnt in school, the formula is:
arithmetic mean = sum/n
where
sum - sum of all numbers (from the given array[] of course)
n - count of the numbers in the given array[]
The purpose of the sum variable is to sum all given numbers, if not equal to 0, and n(in your code amount) just increases for every number added to sum.
And in the end the function should return, as the formula says, sum/amount. I could write this code, i.e. the whole program (except for the random()), though it's quite easy, so I'll leave it up to you.
About the random library, I don't know much, but there are may resources on the net, so take your time.
https://www.tutorialspoint.com/cplusplus-program-to-generate-random-number
https://www.tutorialspoint.com/rand-and-srand-in-c-cplusplus

SPOJ Prime generator Wrong Answer

Here is the link to the problem-:http://www.spoj.com/problems/PRIME1/.
The problem asks to find all prime numbers between a given rang
1 <= m <= n <= 1000000000, n-m<=100000.
I have implemented Segmented Sieve
Here is the logic-:
As the problem has maximum value of 10^9, so I will find all primes withing square_root(10^9) which is around 31622.
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
void Prime1(long int low, long int high, bool* pre)
{
bool prime[high-low+1]={0};
if(low==high)
{if(pre[low]==0)printf("%ld\n", low);return;}
int t=sqrt(high);
for(long int i=2;i<=t;i++)
{
if(pre[i]==1)continue;
long int a=ceil(((double)low/i))*i;// start value
long int b=floor(((double)high/i))*i;// end value
if(a==1)
continue;
if(a==i)
a+=i;
if(a==0)
a=2*i;
for(long int x=a;x<=high;x+=i)
{
prime[x-low]=1;
}
}
if(low==1)
prime[0]=1;
else if(low==0)
prime[0]=prime[1]=1;
for(int i=0;i<=(high-low);i++)
if(!prime[i])printf("%ld\n", i+low);
}
int main()
{
bool pre[32001];
pre[0]=pre[1]=1;
int x=sqrt(32001);
for(int i=2;i<=x;i++)
{
if(pre[i]==0)
{
for(int j=i;i*j<=32000;j++)
{
pre[i*j]=1;
}
}
}
int t;
scanf("%d",&t);
long low, high;
while(t--)
{
scanf("%ld %ld",&low, &high);
printf("\n")
Prime1(low, high, pre);
}
}
Now I'll start from i=2 and find its multiples between m and n. Here m and n represent low and high respectively.
I'll keep on increasing i till i<=sqrt(n)
For example, m=125 and n=140
a=((double)m/i)*i. I'll consider its ceiling value.
So, when m=125 i=2
a=126.
so, 126+(2*k) are all composite where k>=0.
The same is for i=3,5,7.....
When I submit it on SPOJ, it gives me WA.
I have used spoj toolkit which contained some test cases. I compared it with the other code and getting same result.
What am I missing?

Google code jam minimum scalar product not working on my selection sort (c++)

I was practicing previous year's code jam problems and found minimum scalar product.
Problem Link : https://code.google.com/codejam/contest/32016/dashboard#s=p0
I know how its algorithm works. We sort both arrays v1 and v2 then multiply v1[j]*v2[n-1-j]. The algorithm works fine when I use c++ default sort() function. But if i use my own sorting function (selection sort), I get different output.
Further by observing the correct output file i noticed that if all the input numbers and positive my output is correct. However for negative numbers it is incorrect.
Here is the code of my sorting function:
`void sorted(long long int *a,int n)
{
long long int temp;
int minIndex;
for(int i=0;i<n;i++)
{
minIndex=i;
for(int j=i+1;j<n;j++)
{
if(a[i]>a[j])
minIndex=j;
}
if(minIndex!=i)
{
temp=a[minIndex];
a[minIndex]=a[i];
a[i]=temp;
}
}
}
`
Note that for this problem we have to use long long int because input numbers exceed int limits.
This is my main function:
#include <iostream>
#include<fstream>
using namespace std;
void sorted(long long int *a,int n);
int main()
{
ifstream inp("input.in");
int T;
inp>>T;
int n[T];
long long int *x[T], *y[T];
for(int i=0;i<T;i++)
{
inp>>n[i];
x[i]=new long long int[n[i]];
y[i]=new long long int[n[i]];
for(int j=0;j<n[i];j++)
inp>>x[i][j];
for(int j=0;j<n[i];j++)
inp>>y[i][j];
}
long long int minProduct[T];
ofstream out("output.txt");
for(int i=0;i<T;i++)
{
minProduct[i]=0;
sorted(x[i],n[i]);
sorted(y[i],n[i]);
for(int j=0;j<n[i];j++)
minProduct[i]=minProduct[i]+(y[i][n[i]-1-j]*x[i][j]);
out<<"Case #"<<i+1<<": "<<minProduct[i]<<endl;
}
return 0;
}
if i replace
sorted(x[i],n[i]);
sorted(y[i],n[i]);
with
sort(x[i],x[i]+n[i]);
sort(y[i],y[i]+n[i]);
and including algorithm header file, my output is correct.
What is the mistake in my sorting algorithm?
In the loop where you find the minimum index, you must compare the current item at index j with the item at the current index of the minimum item:
minIndex = i;
for (int j = i + 1; j < n; j++) {
if (a[minIndex] > a[j])
minIndex = j;
}
You always compare with the item at index i and hence don't account for updates on minIndex.

Why is this counter increasing in this way and not one by one in this divide and conquer algorithm?

I was reading an algorithm solution to the following problem:
This file contains all of the 100,000 integers between 1 and 100,000 (inclusive) in some order, with no integer repeated.
Your task is to compute the number of inversions in the file given, where the ith row of the file indicates the ith entry of an array.
Because of the large size of this array, you should implement the fast divide-and-conquer algorithm covered in the video lectures.
The numeric answer for the given input file should be typed in the space below.
So the problem gives you the file, but here is the solution:
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#define SIZE 100000
using namespace std;
long long splitInv(long *arr, long l, long u)
{
long *tarr = new long[u-l+2];
long i=l, j=(u-l)/2+l+1, k;
long long count=0;
for(k=1; (k<=u-l+1) && (i<=(u-l)/2+l) && (j<=u); k++)
{
if(arr[i]<arr[j]) tarr[k]=arr[i++];
else
{
tarr[k]=arr[j++];
count=count+((u-l)/2+l-i+1);
}
}
for(; k<=u-l+1 && i<=(u-l)/2+l; k++) tarr[k]=arr[i++];
for(; k<=u-l+1 && j<=u; k++) tarr[k]=arr[j++];
for(k=1, i=l ; k<=u-l+1 && i<=u; k++, i++) arr[i]=tarr[k];
delete tarr;
return count;
}
long long numInv(long *arr, long l, long u)
{
if(u<=l) return 0;
return numInv(arr, l, (u-l)/2+l) + numInv(arr, (u-l)/2+l+1, u) + splitInv(arr, l, u);
}
int main(int argc, char *argv[])
{
long *arr=new long[SIZE+1];
char a[10];
FILE *f=fopen("IntegerArray.txt","r");
for(long i=1; i<=SIZE; i++)
{
fgets(a,10,f);
arr[i]=atol(a);
}
fclose(f);
cout<<"Number of Inversions: "<<numInv(arr,1,SIZE)<<endl;
delete arr;
system("PAUSE");
return EXIT_SUCCESS;
}
So, I was wonder why the counter is increasing by the following way and not one by one, because it's just counting the number of inversions:
count=count+((u-l)/2+l-i+1);
So, for me it should be:
count=count+1;
As you know it is using divide and conquer algorithm it need to ignore the first half if your if condition is not true, so it has to offset your array as shown in your program and not like as you assume .