Count Colorful Strings

Last Updated : 9 Jul, 2026

Find the number of distinct strings of length n that can be formed using only the characters 'R', 'B', and 'G', such that the string contains at least r occurrences of 'R', at least b occurrences of 'B', and at least g occurrences of 'G'.

Examples: 

Input: n = 4, r = 1, b = 1, g = 1
Output: 36
Explanation: With at least one of each character required across a length-4 string, exactly one character is "extra" and can be any of 'R', 'B', or 'G'. This gives three possible character sets: {R,R,B,G}, {R,B,B,G}, and {R,B,G,G}. Each set has 4!/2! = 12 distinct arrangements (since one character repeats), giving 3 × 12 = 36 total strings.

Input: n = 4, r = 2, b = 1, g = 0
Output: 22
Explanation: The valid character distributions, satisfying at least 2 'R', at least 1 'B', and at least 0 'G', are: {R,R,B,G} with 12 arrangements, {R,R,B,B} with 6 arrangements, and {R,R,R,B} with 4 arrangements. Total: 12 + 6 + 4 = 22.

Try It Yourself
redirect icon

[Naive Approach] Using Recursive Generation - O((3^n)*n) Time and O(n) Space

The idea is to recursively build every possible string of length n by choosing 'R', 'B', or 'G' at each position, then check if the final string has enough of each character.

Step by Step Implementation:

  • At each position, try placing 'R', 'B', and 'G', one at a time.
  • Recurse to the next position, tracking how many of each character have been placed so far.
  • Once all n positions are filled, check if the counts meet the required minimums.
  • Count it as valid if they do.
C++
#include <iostream>
using namespace std;

int generate(int pos, int n, int rc, int bc, int gc, int r, int b, int g) {
    
    // All positions filled -- check if the counts meet the minimums
    if (pos == n) return (rc >= r && bc >= b && gc >= g) ? 1 : 0;

    // Try placing 'R', 'B', and 'G' at this position, sum up valid results
    return generate(pos + 1, n, rc + 1, bc, gc, r, b, g)
         + generate(pos + 1, n, rc, bc + 1, gc, r, b, g)
         + generate(pos + 1, n, rc, bc, gc + 1, r, b, g);
}

int countStrings(int n, int r, int b, int g) {
    return generate(0, n, 0, 0, 0, r, b, g);
}

int main() {
    int n = 4, r = 1, b = 1, g = 1;
    cout << countStrings(n, r, b, g) << endl;
    return 0;
}
Java
class GFG {
    static int generate(int pos, int n, int rc, int bc, int gc, int r, int b, int g) {
        
        // All positions filled -- check if the counts meet the minimums
        if (pos == n) return (rc >= r && bc >= b && gc >= g) ? 1 : 0;

        // Try placing 'R', 'B', and 'G' at this position, sum up valid results
        return generate(pos + 1, n, rc + 1, bc, gc, r, b, g)
             + generate(pos + 1, n, rc, bc + 1, gc, r, b, g)
             + generate(pos + 1, n, rc, bc, gc + 1, r, b, g);
    }

    static int countStrings(int n, int r, int b, int g) {
        return generate(0, n, 0, 0, 0, r, b, g);
    }

    public static void main(String[] args) {
        int n = 4, r = 1, b = 1, g = 1;
        System.out.println(countStrings(n, r, b, g));
    }
}
Python
def generate(pos, n, rc, bc, gc, r, b, g):
    
    # All positions filled -- check if the counts meet the minimums
    if pos == n:
        return 1 if (rc >= r and bc >= b and gc >= g) else 0

    # Try placing 'R', 'B', and 'G' at this position, sum up valid results
    return (generate(pos + 1, n, rc + 1, bc, gc, r, b, g)
            + generate(pos + 1, n, rc, bc + 1, gc, r, b, g)
            + generate(pos + 1, n, rc, bc, gc + 1, r, b, g))


def countStrings(n, r, b, g):
    return generate(0, n, 0, 0, 0, r, b, g)


n, r, b, g = 4, 1, 1, 1
print(countStrings(n, r, b, g))
C#
using System;

class GFG {
    static int Generate(int pos, int n, int rc, int bc, int gc, int r, int b, int g) {
        
        // All positions filled -- check if the counts meet the minimums
        if (pos == n) return (rc >= r && bc >= b && gc >= g) ? 1 : 0;

        // Try placing 'R', 'B', and 'G' at this position, sum up valid results
        return Generate(pos + 1, n, rc + 1, bc, gc, r, b, g)
             + Generate(pos + 1, n, rc, bc + 1, gc, r, b, g)
             + Generate(pos + 1, n, rc, bc, gc + 1, r, b, g);
    }

    static int countStrings(int n, int r, int b, int g) {
        return Generate(0, n, 0, 0, 0, r, b, g);
    }

    static void Main() {
        int n = 4, r = 1, b = 1, g = 1;
        Console.WriteLine(countStrings(n, r, b, g));
    }
}
JavaScript
function generate(pos, n, rc, bc, gc, r, b, g) {
    // All positions filled -- check if the counts meet the minimums
    if (pos === n) return (rc >= r && bc >= b && gc >= g) ? 1 : 0;

    // Try placing 'R', 'B', and 'G' at this position, sum up valid results
    return generate(pos + 1, n, rc + 1, bc, gc, r, b, g)
         + generate(pos + 1, n, rc, bc + 1, gc, r, b, g)
         + generate(pos + 1, n, rc, bc, gc + 1, r, b, g);
}

function countStrings(n, r, b, g) {
    return generate(0, n, 0, 0, 0, r, b, g);
}

// Driver Code
const n = 4, r = 1, b = 1, g = 1;
console.log(countStrings(n, r, b, g));

Output
36

[Expected Approach] Using Formula and Precomputed Factorials - O(n*n) Time and O(n) Space

 The idea is to directly count valid character distributions instead of generating every string. For every way to split n positions into x R's, y B's, and z G's (with x ≥ r, y ≥ b, z ≥ g), the number of strings with that exact distribution is the coefficient n! / (x! × y! × z!). Precomputing factorials lets each coefficient be computed in O(1).

Step by Step Implementation:

  • Precompute factorials from 0! to n!.
  • Try every valid count of R's (x, from r to n) and B's (y, from b, as long as x+y ≤ n).
  • Compute z = n - x - y, and check if z ≥ g.
  • If valid, add n! / (x! × y! × z!) to the total.
  • Return the total.
C++
#include <iostream>
#include <vector>
using namespace std;

int countStrings(int n, int r, int b, int g) {
    
    // Precompute factorials 0! through n!
    vector<long long> fact(n + 1);
    fact[0] = 1;
    for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i;

    // Try every valid split (x, y, z) with x>=r, y>=b, z>=g, x+y+z=n
    long long total = 0;
    for (int x = r; x <= n; x++) {
        for (int y = b; x + y <= n; y++) {
            int z = n - x - y;
            if (z >= g) {
                total += fact[n] / (fact[x] * fact[y] * fact[z]);
            }
        }
    }
    return (int)total;
}

int main() {
    int n = 4, r = 1, b = 1, g = 1;
    cout << countStrings(n, r, b, g) << endl;
    return 0;
}
Java
class GFG {
    static int countStrings(int n, int r, int b, int g) {
        
        // Precompute factorials 0! through n!
        long[] fact = new long[n + 1];
        fact[0] = 1;
        for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i;

        // Try every valid split (x, y, z) with x>=r, y>=b, z>=g, x+y+z=n
        long total = 0;
        for (int x = r; x <= n; x++) {
            for (int y = b; x + y <= n; y++) {
                int z = n - x - y;
                if (z >= g) {
                    total += fact[n] / (fact[x] * fact[y] * fact[z]);
                }
            }
        }
        return (int) total;
    }

    public static void main(String[] args) {
        int n = 4, r = 1, b = 1, g = 1;
        System.out.println(countStrings(n, r, b, g));
    }
}
Python
def countStrings(n, r, b, g):
    
    # Precompute factorials 0! through n!
    fact = [1] * (n + 1)
    for i in range(1, n + 1):
        fact[i] = fact[i - 1] * i

    # Try every valid split (x, y, z) with x>=r, y>=b, z>=g, x+y+z=n
    total = 0
    for x in range(r, n + 1):
        y = b
        while x + y <= n:
            z = n - x - y
            if z >= g:
                total += fact[n] // (fact[x] * fact[y] * fact[z])
            y += 1
    return total


n, r, b, g = 4, 1, 1, 1
print(countStrings(n, r, b, g))
C#
using System;

class GFG {
    static int countStrings(int n, int r, int b, int g) {
        
        // Precompute factorials 0! through n!
        long[] fact = new long[n + 1];
        fact[0] = 1;
        for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i;

        // Try every valid split (x, y, z) with x>=r, y>=b, z>=g, x+y+z=n
        long total = 0;
        for (int x = r; x <= n; x++) {
            for (int y = b; x + y <= n; y++) {
                int z = n - x - y;
                if (z >= g) {
                    total += fact[n] / (fact[x] * fact[y] * fact[z]);
                }
            }
        }
        return (int)total;
    }

    static void Main() {
        int n = 4, r = 1, b = 1, g = 1;
        Console.WriteLine(countStrings(n, r, b, g));
    }
}
JavaScript
function countStrings(n, r, b, g) {
    
    // Precompute factorials 0! through n!
    const fact = new Array(n + 1).fill(1);
    for (let i = 1; i <= n; i++) fact[i] = fact[i - 1] * i;

    // Try every valid split (x, y, z) with x>=r, y>=b, z>=g, x+y+z=n
    let total = 0;
    for (let x = r; x <= n; x++) {
        for (let y = b; x + y <= n; y++) {
            const z = n - x - y;
            if (z >= g) {
                total += fact[n] / (fact[x] * fact[y] * fact[z]);
            }
        }
    }
    return total;
}

// Driver Code
const n = 4, r = 1, b = 1, g = 1;
console.log(countStrings(n, r, b, g));

Output
36
Comment