Given N number of coins, the task is to find probability of getting at least K number of heads after tossing all the N coins simultaneously.
Example :
Suppose we have 3 unbiased coins and we have to
find the probability of getting at least 2 heads,
so there are 23 = 8 ways to toss these
coins, i.e.,
HHH, HHT, HTH, HTT, THH, THT, TTH, TTT
Out of which there are 4 set which contain at
least 2 Heads i.e.,
HHH, HHT, HH, THH
So the probability is 4/8 or 0.5
The probability of exactly k success in n trials with probability p of success in any trial is given by:

So Probability ( getting at least 4 heads )=


Method 1 (Naive)
A Naive approach is to store the value of factorial in dp[] array and call it directly whenever it is required. But the problem of this approach is that we can only able to store it up to certain value, after that it will lead to overflow.
Below is the implementation of above approach
C++
#include<bits/stdc++.h>
using namespace std;
#define MAX 21
double fact[MAX];
double probability( int k, int n)
{
double ans = 0;
for ( int i = k; i <= n; ++i)
ans += fact[n] / (fact[i] * fact[n - i]);
ans = ans / (1LL << n);
return ans;
}
void precompute()
{
fact[0] = fact[1] = 1;
for ( int i = 2; i < 20; ++i)
fact[i] = fact[i - 1] * i;
}
int main()
{
precompute();
cout << probability(2, 3) << "\n" ;
cout << probability(3, 6) << "\n" ;
cout << probability(12, 18);
return 0;
}
|
Java
import java.io.*;
class GFG {
public static double fact[];
public static double probability( int k, int n)
{
double ans = 0 ;
for ( int i = k; i <= n; ++ i)
ans += fact[n] / (fact[i] * fact[n-i]);
ans = ans / ( 1 << n);
return ans;
}
public static void precompute()
{
fact[ 0 ] = fact[ 1 ] = 1 ;
for ( int i = 2 ; i < 20 ; ++i)
fact[i] = fact[i - 1 ] * i;
}
public static void main(String[] args)
{
fact = new double [ 100 ];
precompute();
System.out.println(probability( 2 , 3 ));
System.out.println(probability( 3 , 6 ));
System.out.println(probability( 12 , 18 ));
}
}
|
Python3
MAX = 21
fact = [ 0 ] * MAX
def probability(k, n):
ans = 0
for i in range (k,n + 1 ):
ans + = fact[n] / (fact[i] * fact[n - i])
ans = ans / ( 1 << n)
return ans
def precompute():
fact[ 0 ] = 1
fact[ 1 ] = 1
for i in range ( 2 , 20 ):
fact[i] = fact[i - 1 ] * i
if __name__ = = '__main__' :
precompute()
print (probability( 2 , 3 ))
print (probability( 3 , 6 ))
print (probability( 12 , 18 ))
|
C#
using System;
class GFG
{
public static double []fact;
public static double probability( int k, int n)
{
double ans = 0;
for ( int i = k; i <= n; ++ i)
ans += fact[n] / (fact[i] * fact[n - i]);
ans = ans / (1 << n);
return ans;
}
public static void precompute()
{
fact[0] = fact[1] = 1;
for ( int i = 2; i < 20; ++i)
fact[i] = fact[i - 1] * i;
}
public static void Main()
{
fact = new double [100];
precompute();
Console.WriteLine(probability(2, 3));
Console.WriteLine(probability(3, 6));
Console.Write(probability(12, 18));
}
}
|
PHP
<?php
$MAX = 21;
$fact = array_fill (0, $MAX , 0);
function probability( $k , $n )
{
global $fact ;
$ans = 0;
for ( $i = $k ; $i <= $n ; ++ $i )
$ans += $fact [ $n ] / ( $fact [ $i ] *
$fact [ $n - $i ]);
$ans = $ans / (1 << $n );
return $ans ;
}
function precompute()
{
global $fact ;
$fact [0] = $fact [1] = 1;
for ( $i = 2; $i < 20; ++ $i )
$fact [ $i ] = $fact [ $i - 1] * $i ;
}
precompute();
echo number_format(probability(2, 3), 6) . "\n" ;
echo number_format(probability(3, 6), 6) . "\n" ;
echo number_format(probability(12, 18), 6);
?>
|
Javascript
<script>
let fact;
function probability( k, n) {
let ans = 0, i;
for ( i = k; i <= n; ++i)
ans += fact[n] / (fact[i] * fact[n - i]);
ans = ans / (1 << n);
return ans;
}
function precompute() {
fact[0] = fact[1] = 1;
for ( let i = 2; i < 20; ++i)
fact[i] = fact[i - 1] * i;
}
fact = Array(100).fill(0);
precompute();
document.write(probability(2, 3)+ "<br/>" );
document.write(probability(3, 6)+ "<br/>" );
document.write(probability(12, 18).toFixed(6)+ "<br/>" );
</script>
|
Output0.5
0.65625
0.118942
Time Complexity: O(n) where n < 20
Auxiliary space: O(n)
Method 2 (Dynamic Programming and Log)
Another way is to use Dynamic programming and logarithm. log() is indeed useful to store the factorial of any number without worrying about overflow. Let’s see how we use it:
At first let see how n! can be written.
n! = n * (n-1) * (n-2) * (n-3) * ... * 3 * 2 * 1
Now take log on base 2 both the sides as:
=> log(n!) = log(n) + log(n-1) + log(n-2) + ... + log(3)
+ log(2) + log(1)
Now whenever we need to find the factorial of any number, we can use
this precomputed value. For example:
Suppose if we want to find the value of nCi which can be written as:
=> nCi = n! / (i! * (n-i)! )
Taking log2() both sides as:
=> log2 (nCi) = log2 ( n! / (i! * (n-i)! ) )
=> log2 (nCi) = log2 ( n! ) - log2(i!) - log2( (n-i)! ) `
Putting dp[num] = log2 (num!), we get:
=> log2 (nCi) = dp[n] - dp[i] - dp[n-i]
But as we see in above relation there is an extra factor of 2n which
tells the probability of getting i heads, so
=> log2 (2n) = n.
We will subtract this n from above result to get the final answer:
=> Pi (log2 (nCi)) = dp[n] - dp[i] - dp[n-i] - n
Now: Pi (nCi) = 2 dp[n] - dp[i] - dp[n-i] - n
Tada! Now the questions boils down the summation of Pi for all i in
[k, n] will yield the answer which can be calculated easily without
overflow.
Below are the codes to illustrate this:
C++
#include<bits/stdc++.h>
using namespace std;
#define MAX 100001
double dp[MAX];
double probability( int k, int n)
{
double ans = 0;
for ( int i=k; i <= n; ++i)
{
double res = dp[n] - dp[i] - dp[n-i] - n;
ans += pow (2.0, res);
}
return ans;
}
void precompute()
{
for ( int i=2; i < MAX; ++i)
dp[i] = log2(i) + dp[i-1];
}
int main()
{
precompute();
cout << probability(2, 3) << "\n" ;
cout << probability(3, 6) << "\n" ;
cout << probability(500, 1000);
return 0;
}
|
Java
import java.io.*;
import java.math.*;
class GFG {
static int MAX = 100001 ;
static double dp[] = new double [MAX];
static double probability( int k, int n)
{
double ans = 0.0 ;
for ( int i=k; i <= n; ++i)
{
double res = dp[n] - dp[i] - dp[n-i] - n;
ans += Math.pow( 2.0 , res);
}
return ans;
}
static void precompute()
{
for ( int i= 2 ; i < MAX; ++i)
dp[i] = (Math.log(i)/Math.log( 2 )) + dp[i- 1 ];
}
public static void main(String args[])
{
precompute();
System.out.println(probability( 2 , 3 ));
System.out.println(probability( 3 , 6 ));
System.out.println(probability( 500 , 1000 ));
}
}
|
Python3
from math import log2
MAX = 100001
dp = [ 0 ] * MAX
def probability( k, n):
ans = 0
for i in range (k,n + 1 ):
res = dp[n] - dp[i] - dp[n - i] - n
ans = ans + pow ( 2.0 , res)
return ans
def precompute():
for i in range ( 2 , MAX ):
dp[i] = log2(i) + dp[i - 1 ]
if __name__ = = '__main__' :
precompute()
print (probability( 2 , 3 ))
print (probability( 3 , 6 ))
print (probability( 500 , 1000 ))
|
C#
using System;
class GFG
{
static int MAX = 100001;
static double [] dp = new double [MAX];
static double probability( int k, int n)
{
double ans = 0.0;
for ( int i = k; i <= n; ++i)
{
double res = dp[n] - dp[i] - dp[n-i] - n;
ans += Math.Pow(2.0, res);
}
return ans;
}
static void precompute()
{
for ( int i = 2; i < MAX; ++i)
dp[i] = (Math.Log(i) / Math.Log(2)) + dp[i - 1];
}
public static void Main()
{
precompute();
Console.WriteLine(probability(2, 3));
Console.WriteLine(probability(3, 6));
Console.WriteLine(Math.Round(probability(500, 1000),6));
}
}
|
PHP
<?php
$MAX = 100001;
$dp = array_fill (0, $MAX , 0);
function probability( $k , $n )
{
global $MAX , $dp ;
$ans = 0;
for ( $i = $k ; $i <= $n ; ++ $i )
{
$res = $dp [ $n ] - $dp [ $i ] -
$dp [ $n - $i ] - $n ;
$ans += pow(2.0, $res );
}
return $ans ;
}
function precompute()
{
global $MAX , $dp ;
for ( $i = 2; $i < $MAX ; ++ $i )
$dp [ $i ] = log( $i , 2) + $dp [ $i - 1];
}
precompute();
echo probability(2, 3). "\n" ;
echo probability(3, 6). "\n" ;
echo probability(500, 1000);
?>
|
Javascript
<script>
let MAX = 100001;
let dp = new Array(MAX).fill(0);
function probability(k , n)
{
var ans = 0.0;
for (let i = k; i <= n; ++i)
{
var res = dp[n] - dp[i] - dp[n - i] - n;
ans += Math.pow(2.0, res);
}
return ans;
}
function precompute()
{
for (let i = 2; i < MAX; ++i)
dp[i] = (Math.log(i) / Math.log(2)) + dp[i - 1];
}
precompute();
document.write(probability(2, 3).toFixed(2)+ "<br/>" );
document.write(probability(3, 6).toFixed(5)+ "<br/>" );
document.write(probability(500, 1000).toFixed(6)+ "<br/>" );
</script>
|
Output0.5
0.65625
0.512613
Time Complexity: O(n)
Auxiliary space: O(n)
This approach is beneficial for large value of n ranging from 1 to 106
This article is contributed by Shubham Bansal. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.