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.

For example:

Suppose we have 3 unbiased coins and we have to find the probability of getting at least 2 heads, so there are 2^{3}= 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 C++ implementation of above approach

// Naive approach in C++ to find probability of // at least k heads #include<bits/stdc++.h> using namespace std; #define MAX 21 double fact[MAX]; // Returns probability of getting at least k // heads in n tosses. double probability(int k, int n) { double ans = 0; for (int i=k; i <= n; ++i) // Probability of getting exactly i // heads out of n heads ans += fact[n]/(fact[i] * fact[n-i]); // Note: 1 << n = pow(2, n) ans = ans/(1LL << n); return ans; } void precompute() { // Preprocess all factorial only upto 19, // as after that it will overflow fact[0] = fact[1] = 1; for (int i=2; i < 20; ++i) fact[i] = fact[i-1] * i; } // Drive code int main() { precompute(); // Probability of getting 2 head out of 3 coins cout << probability(2, 3) << "\n"; // Probability of getting 3 head out of 6 coins cout << probability(3, 6) <<"\n"; // Probability of getting 12 head out of 18 coins cout << probability(12, 18); return 0; }

**Output: **

0.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 * 1Now 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=>^{n}C_{i}which can be written as:^{n}C_{i}= n! / (i! * (n-i)! )Taking log=> log_{2}() both sides as:_{2}(^{n}C_{i}) = log_{2}( n! / (i! * (n-i)! ) ) => log_{2}(^{n}C_{i}) = log_{2}( n! ) - log_{2}(i!) - log_{2}( (n-i)! ) `Putting dp[num] = log=> log_{2}(num!), we get:_{2}(^{n}C_{i}) = dp[n] - dp[i] - dp[n-i]But as we see in above relation there is an extra factor of 2=> log^{n}which tells the probability of getting i heads, so_{2}(2^{n}) = n.We will subtract this n from above result to get the final answer:=> P_{i}(log_{2}(^{n}C_{i})) = dp[n] - dp[i] - dp[n-i] - nNow:P_{i}(^{n}C_{i}) = 2^{dp[n] - dp[i] - dp[n-i] - n}Tada! Now the questions boils down the summation of P_{i}for all i in [k, n] will yield the answer which can be calculated easily without overflow.

Below is C++ code to illustrate this:

// Dynamic and Logarithm approach find probability of // at least k heads #include<bits/stdc++.h> using namespace std; #define MAX 100001 // dp[i] is going to store Log ( i !) in base 2 double dp[MAX]; double probability(int k, int n) { double ans = 0; // Initialize result // Iterate from k heads to n heads for (int i=k; i <= n; ++i) { int res = dp[n] - dp[i] - dp[n-i] - n; ans += pow(2.0, res); } return ans; } void precompute() { // Preprocess all the logarithm value on base 2 for (int i=2; i < MAX; ++i) dp[i] = log2(i) + dp[i-1]; } // Drive code int main() { precompute(); // Probability of getting 2 head out of 3 coins cout << probability(2, 3) << "\n"; // Probability of getting 3 head out of 6 coins cout << probability(3, 6) << "\n"; // Probability of getting 500 head out of 10000 coins cout << probability(500, 1000); return 0; }

**Output:**

0.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 10 ^{6}**

This article is contributed by Shubham Bansal. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@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.