Given three integers p, q, and r representing the number of balls of type P, Q, and R, respectively, return the total number of distinct arrangements of all the balls such that no two adjacent balls are of the same type. Since the answer can be very large, return it modulo 10^9 + 7.
Note: Balls of the same type are considered identical. Only the order of the ball types in the arrangement matters.
Examples:
Input: p = 2, q = 2, r = 2
Output: 30
Explanation: There are 30 valid arrangements in which no two adjacent balls are of the same type. Some possible arrangements are PQRPQR, PQRPRQ, PRQPQR, PRQPRQ, and QRPRPQ.Input: p = 1, q = 1, r = 1
Output: 6
Explanation: The valid arrangements are PQR, PRQ, QPR, QRP, RPQ, and RQP.
Table of Content
[Naive Approach] Using Recursion – O(3^n) Time and O(n) Space
The idea is to build the arrangement one ball at a time while keeping track of the type of the previously placed ball. At each step, we can choose P, Q, or R, but we cannot choose the same type as the previous ball. We recursively explore all valid choices by reducing the count of the selected ball, and whenever all balls are used, we count one valid arrangement.
Recurrence Relation:
- if the last ball is of type P: countUtil(p, q, r, last) = countUtil(p-1, q, r, 1) + countUtil(p-1, q, r, 2)
- if the last ball is of type Q: countUtil(p, q, r, last) = countUtil(p, q-1, r, 0) + countUtil(p, q-1, r, 2)
- if the last ball is of type R: countUtil(p, q, r, last) = countUtil(p, q, r-1, 0) + countUtil(p, q-1, r-1, 1)
Base Cases:
if (p < 0), (q < 0) or (r < 0) then countWays(p, q, r, last) = 0. if only one ball ramains of specific type, then:
- countUtil(p, q, r, 0) = 1 if p=1 and q=0 and r=0
- countUtil(p, q, r, 1) = 1 if p=0 and q=1 and r=0
- countUtil(p, q, r, 2) = 1 if p=0 and q=0 and r=1
#include <iostream>
using namespace std;
int countUtil(int p, int q, int r, int last)
{
// If any count becomes negative, this arrangement
// is not possible.
if (p < 0 || q < 0 || r < 0)
return 0;
// If only one P ball is remaining and P is required
// at the last position, there is exactly one way.
if (p == 1 && q == 0 && r == 0 && last == 0)
return 1;
// If only one Q ball is remaining and Q is required
// at the last position, there is exactly one way.
if (p == 0 && q == 1 && r == 0 && last == 1)
return 1;
// If only one R ball is remaining and R is required
// at the last position, there is exactly one way.
if (p == 0 && q == 0 && r == 1 && last == 2)
return 1;
// If P is required at the current position,
// the previous ball must be Q or R.
if (last == 0)
{
return countUtil(p - 1, q, r, 1) + countUtil(p - 1, q, r, 2);
}
// If Q is required at the current position,
// the previous ball must be P or R.
if (last == 1)
{
return countUtil(p, q - 1, r, 0) + countUtil(p, q - 1, r, 2);
}
// If R is required at the current position,
// the previous ball must be P or Q.
if (last == 2)
{
return countUtil(p, q, r - 1, 0) + countUtil(p, q, r - 1, 1);
}
return 0;
}
int arrangeBalls(int p, int q, int r)
{
// The last ball can be P, Q, or R.
return countUtil(p, q, r, 0) + countUtil(p, q, r, 1) + countUtil(p, q, r, 2);
}
int main()
{
int p = 1, q = 1, r = 1;
int res = arrangeBalls(p, q, r);
cout << res << endl;
return 0;
}
import java.util.*;
class GFG {
static int countUtil(int p, int q, int r, int last)
{
// If any count becomes negative, this arrangement
// is not possible.
if (p < 0 || q < 0 || r < 0)
return 0;
// If only one P ball is remaining and P is required
// at the last position, there is exactly one way.
if (p == 1 && q == 0 && r == 0 && last == 0)
return 1;
// If only one Q ball is remaining and Q is required
// at the last position, there is exactly one way.
if (p == 0 && q == 1 && r == 0 && last == 1)
return 1;
// If only one R ball is remaining and R is required
// at the last position, there is exactly one way.
if (p == 0 && q == 0 && r == 1 && last == 2)
return 1;
// If P is required at the current position,
// the previous ball must be Q or R.
if (last == 0) {
return countUtil(p - 1, q, r, 1)
+ countUtil(p - 1, q, r, 2);
}
// If Q is required at the current position,
// the previous ball must be P or R.
if (last == 1) {
return countUtil(p, q - 1, r, 0)
+ countUtil(p, q - 1, r, 2);
}
// If R is required at the current position,
// the previous ball must be P or Q.
if (last == 2) {
return countUtil(p, q, r - 1, 0)
+ countUtil(p, q, r - 1, 1);
}
return 0;
}
static int arrangeBalls(int p, int q, int r)
{
// The last ball can be P, Q, or R.
return countUtil(p, q, r, 0) + countUtil(p, q, r, 1)
+ countUtil(p, q, r, 2);
}
public static void main(String[] args)
{
int p = 1, q = 1, r = 1;
int res = arrangeBalls(p, q, r);
System.out.println(res);
}
}
def countUtil(p, q, r, last):
# If any count becomes negative, this arrangement
# is not possible.
if p < 0 or q < 0 or r < 0:
return 0
# If only one P ball is remaining and P is required
# at the last position, there is exactly one way.
if p == 1 and q == 0 and r == 0 and last == 0:
return 1
# If only one Q ball is remaining and Q is required
# at the last position, there is exactly one way.
if p == 0 and q == 1 and r == 0 and last == 1:
return 1
# If only one R ball is remaining and R is required
# at the last position, there is exactly one way.
if p == 0 and q == 0 and r == 1 and last == 2:
return 1
# If P is required at the current position,
# the previous ball must be Q or R.
if last == 0:
return countUtil(p - 1, q, r, 1) + \
countUtil(p - 1, q, r, 2)
# If Q is required at the current position,
# the previous ball must be P or R.
if last == 1:
return countUtil(p, q - 1, r, 0) + \
countUtil(p, q - 1, r, 2)
# If R is required at the current position,
# the previous ball must be P or Q.
if last == 2:
return countUtil(p, q, r - 1, 0) + \
countUtil(p, q, r - 1, 1)
return 0
def arrangeBalls(p, q, r):
# The last ball can be P, Q, or R.
return countUtil(p, q, r, 0) + \
countUtil(p, q, r, 1) + \
countUtil(p, q, r, 2)
# Driver code
if __name__ == "__main__":
p = 1
q = 1
r = 1
res = arrangeBalls(p, q, r)
print(res)
using System;
class GFG {
static int CountUtil(int p, int q, int r, int last)
{
// If any count becomes negative, this arrangement
// is not possible.
if (p < 0 || q < 0 || r < 0)
return 0;
// If only one P ball is remaining and P is required
// at the last position, there is exactly one way.
if (p == 1 && q == 0 && r == 0 && last == 0)
return 1;
// If only one Q ball is remaining and Q is required
// at the last position, there is exactly one way.
if (p == 0 && q == 1 && r == 0 && last == 1)
return 1;
// If only one R ball is remaining and R is required
// at the last position, there is exactly one way.
if (p == 0 && q == 0 && r == 1 && last == 2)
return 1;
// If P is required at the current position,
// the previous ball must be Q or R.
if (last == 0) {
return CountUtil(p - 1, q, r, 1)
+ CountUtil(p - 1, q, r, 2);
}
// If Q is required at the current position,
// the previous ball must be P or R.
if (last == 1) {
return CountUtil(p, q - 1, r, 0)
+ CountUtil(p, q - 1, r, 2);
}
// If R is required at the current position,
// the previous ball must be P or Q.
if (last == 2) {
return CountUtil(p, q, r - 1, 0)
+ CountUtil(p, q, r - 1, 1);
}
return 0;
}
static int arrangeBalls(int p, int q, int r)
{
// The last ball can be P, Q, or R.
return CountUtil(p, q, r, 0) + CountUtil(p, q, r, 1)
+ CountUtil(p, q, r, 2);
}
public static void Main()
{
int p = 1, q = 1, r = 1;
int res = arrangeBalls(p, q, r);
Console.WriteLine(res);
}
}
function countUtil(p, q, r, last)
{
// If any count becomes negative, this arrangement
// is not possible.
if (p < 0 || q < 0 || r < 0)
return 0;
// If only one P ball is remaining and P is required
// at the last position, there is exactly one way.
if (p === 1 && q === 0 && r === 0 && last === 0)
return 1;
// If only one Q ball is remaining and Q is required
// at the last position, there is exactly one way.
if (p === 0 && q === 1 && r === 0 && last === 1)
return 1;
// If only one R ball is remaining and R is required
// at the last position, there is exactly one way.
if (p === 0 && q === 0 && r === 1 && last === 2)
return 1;
// If P is required at the current position,
// the previous ball must be Q or R.
if (last === 0) {
return countUtil(p - 1, q, r, 1)
+ countUtil(p - 1, q, r, 2);
}
// If Q is required at the current position,
// the previous ball must be P or R.
if (last === 1) {
return countUtil(p, q - 1, r, 0)
+ countUtil(p, q - 1, r, 2);
}
// If R is required at the current position,
// the previous ball must be P or Q.
if (last === 2) {
return countUtil(p, q, r - 1, 0)
+ countUtil(p, q, r - 1, 1);
}
return 0;
}
function arrangeBalls(p, q, r)
{
// The last ball can be P, Q, or R.
return countUtil(p, q, r, 0) + countUtil(p, q, r, 1)
+ countUtil(p, q, r, 2);
}
// Driver code
let p = 1, q = 1, r = 1;
let res = arrangeBalls(p, q, r);
console.log(res);
Output
6
Consider the following example for better understanding: p = 1, q = 1, r = 1, and last = p

[Better Approach] Using Top-Down DP (Memoization) - O(p*q*r) Time and O(p*q*r) Space
The idea is to optimize the recursive solution by storing the result of every state (p, q, r, last). The same state can be reached through different arrangements, so recomputing it is unnecessary. We store each computed result in a 4D DP table and directly return it whenever the same state appears again.
- Define countUtil(p, q, r, last) and use dp[p][q][r][last] to store its result.
- Handle invalid states and the base cases where only the required ball remains.
- Before recursion, check whether the current state has already been calculated; if yes, return the stored value.
- For P, recursively consider previous balls Q and R; similarly handle Q and R.
- Store the calculated result in dp[p][q][r][last] before returning it.
- Add the results for the three possible last balls P, Q, and R.
#include <iostream>
#include <vector>
using namespace std;
const int MOD = 1000000007;
vector<vector<vector<vector<int>>>> dp;
int countUtil(int p, int q, int r, int last)
{
// If any count becomes negative, this arrangement
// is not possible.
if (p < 0 || q < 0 || r < 0)
return 0;
// If only one P ball is remaining and P is required
// at the last position, there is exactly one way.
if (p == 1 && q == 0 && r == 0 && last == 0)
return 1;
// If only one Q ball is remaining and Q is required
// at the last position, there is exactly one way.
if (p == 0 && q == 1 && r == 0 && last == 1)
return 1;
// If only one R ball is remaining and R is required
// at the last position, there is exactly one way.
if (p == 0 && q == 0 && r == 1 && last == 2)
return 1;
// If this state has already been calculated,
// return the stored result.
if (dp[p][q][r][last] != -1)
return dp[p][q][r][last];
long long ans = 0;
// If P is required at the current position,
// the previous ball must be Q or R.
if (last == 0)
{
ans = (ans + countUtil(p - 1, q, r, 1)) % MOD;
ans = (ans + countUtil(p - 1, q, r, 2)) % MOD;
}
// If Q is required at the current position,
// the previous ball must be P or R.
if (last == 1)
{
ans = (ans + countUtil(p, q - 1, r, 0)) % MOD;
ans = (ans + countUtil(p, q - 1, r, 2)) % MOD;
}
// If R is required at the current position,
// the previous ball must be P or Q.
if (last == 2)
{
ans = (ans + countUtil(p, q, r - 1, 0)) % MOD;
ans = (ans + countUtil(p, q, r - 1, 1)) % MOD;
}
// Store and return the result of this state.
return dp[p][q][r][last] = ans % MOD;
}
int arrangeBalls(int p, int q, int r)
{
// Initialize the DP table with -1.
dp.assign(p + 1, vector<vector<vector<int>>>(q + 1, vector<vector<int>>(r + 1, vector<int>(3, -1))));
long long ans = 0;
// The last ball can be P, Q, or R.
ans = (ans + countUtil(p, q, r, 0)) % MOD;
ans = (ans + countUtil(p, q, r, 1)) % MOD;
ans = (ans + countUtil(p, q, r, 2)) % MOD;
return ans;
}
int main()
{
int p = 1, q = 1, r = 1;
int res = arrangeBalls(p, q, r);
cout << res << endl;
return 0;
}
import java.util.*;
class GFG {
static final int MOD = 1000000007;
static int[][][][] dp;
static int countUtil(int p, int q, int r, int last)
{
// If any count becomes negative, this arrangement
// is not possible.
if (p < 0 || q < 0 || r < 0)
return 0;
// If only one P ball is remaining and P is required
// at the last position, there is exactly one way.
if (p == 1 && q == 0 && r == 0 && last == 0)
return 1;
// If only one Q ball is remaining and Q is required
// at the last position, there is exactly one way.
if (p == 0 && q == 1 && r == 0 && last == 1)
return 1;
// If only one R ball is remaining and R is required
// at the last position, there is exactly one way.
if (p == 0 && q == 0 && r == 1 && last == 2)
return 1;
// If this state has already been calculated,
// return the stored result.
if (dp[p][q][r][last] != -1)
return dp[p][q][r][last];
long ans = 0;
// If P is required at the current position,
// the previous ball must be Q or R.
if (last == 0) {
ans = (ans + countUtil(p - 1, q, r, 1)) % MOD;
ans = (ans + countUtil(p - 1, q, r, 2)) % MOD;
}
// If Q is required at the current position,
// the previous ball must be P or R.
if (last == 1) {
ans = (ans + countUtil(p, q - 1, r, 0)) % MOD;
ans = (ans + countUtil(p, q - 1, r, 2)) % MOD;
}
// If R is required at the current position,
// the previous ball must be P or Q.
if (last == 2) {
ans = (ans + countUtil(p, q, r - 1, 0)) % MOD;
ans = (ans + countUtil(p, q, r - 1, 1)) % MOD;
}
// Store and return the result of this state.
return dp[p][q][r][last] = (int)(ans % MOD);
}
static int arrangeBalls(int p, int q, int r)
{
// Initialize the DP table with -1.
dp = new int[p + 1][q + 1][r + 1][3];
// Fill the entire DP table with -1.
for (int i = 0; i <= p; i++) {
for (int j = 0; j <= q; j++) {
for (int k = 0; k <= r; k++) {
Arrays.fill(dp[i][j][k], -1);
}
}
}
long ans = 0;
// The last ball can be P, Q, or R.
ans = (ans + countUtil(p, q, r, 0)) % MOD;
ans = (ans + countUtil(p, q, r, 1)) % MOD;
ans = (ans + countUtil(p, q, r, 2)) % MOD;
return (int)ans;
}
public static void main(String[] args)
{
int p = 1, q = 1, r = 1;
int res = arrangeBalls(p, q, r);
System.out.println(res);
}
}
def countUtil(p, q, r, last, MOD, dp):
# If any count becomes negative, this arrangement
# is not possible.
if p < 0 or q < 0 or r < 0:
return 0
# If only one P ball is remaining and P is required
# at the last position, there is exactly one way.
if p == 1 and q == 0 and r == 0 and last == 0:
return 1
# If only one Q ball is remaining and Q is required
# at the last position, there is exactly one way.
if p == 0 and q == 1 and r == 0 and last == 1:
return 1
# If only one R ball is remaining and R is required
# at the last position, there is exactly one way.
if p == 0 and q == 0 and r == 1 and last == 2:
return 1
# If this state has already been calculated,
# return the stored result.
if dp[p][q][r][last] != -1:
return dp[p][q][r][last]
ans = 0
# If P is required at the current position,
# the previous ball must be Q or R.
if last == 0:
ans = (ans + countUtil(p - 1, q, r, 1, MOD, dp)) % MOD
ans = (ans + countUtil(p - 1, q, r, 2, MOD, dp)) % MOD
# If Q is required at the current position,
# the previous ball must be P or R.
if last == 1:
ans = (ans + countUtil(p, q - 1, r, 0, MOD, dp)) % MOD
ans = (ans + countUtil(p, q - 1, r, 2, MOD, dp)) % MOD
# If R is required at the current position,
# the previous ball must be P or Q.
if last == 2:
ans = (ans + countUtil(p, q, r - 1, 0, MOD, dp)) % MOD
ans = (ans + countUtil(p, q, r - 1, 1, MOD, dp)) % MOD
# Store and return the result of this state.
dp[p][q][r][last] = ans % MOD
return dp[p][q][r][last]
def arrangeBalls(p, q, r):
MOD = 1000000007
# Initialize the DP table with -1.
dp = [
[
[
[-1 for _ in range(3)]
for _ in range(r + 1)
]
for _ in range(q + 1)
]
for _ in range(p + 1)
]
ans = 0
# The last ball can be P, Q, or R.
ans = (ans + countUtil(p, q, r, 0, MOD, dp)) % MOD
ans = (ans + countUtil(p, q, r, 1, MOD, dp)) % MOD
ans = (ans + countUtil(p, q, r, 2, MOD, dp)) % MOD
return ans
# Driver code
if __name__ == "__main__":
p = 1
q = 1
r = 1
res = arrangeBalls(p, q, r)
print(res)
using System;
class GFG {
const int MOD = 1000000007;
static int[, , , ] dp;
static int CountUtil(int p, int q, int r, int last)
{
// If any count becomes negative, this arrangement
// is not possible.
if (p < 0 || q < 0 || r < 0)
return 0;
// If only one P ball is remaining and P is required
// at the last position, there is exactly one way.
if (p == 1 && q == 0 && r == 0 && last == 0)
return 1;
// If only one Q ball is remaining and Q is required
// at the last position, there is exactly one way.
if (p == 0 && q == 1 && r == 0 && last == 1)
return 1;
// If only one R ball is remaining and R is required
// at the last position, there is exactly one way.
if (p == 0 && q == 0 && r == 1 && last == 2)
return 1;
// If this state has already been calculated,
// return the stored result.
if (dp[p, q, r, last] != -1)
return dp[p, q, r, last];
long ans = 0;
// If P is required at the current position,
// the previous ball must be Q or R.
if (last == 0) {
ans = (ans + CountUtil(p - 1, q, r, 1)) % MOD;
ans = (ans + CountUtil(p - 1, q, r, 2)) % MOD;
}
// If Q is required at the current position,
// the previous ball must be P or R.
if (last == 1) {
ans = (ans + CountUtil(p, q - 1, r, 0)) % MOD;
ans = (ans + CountUtil(p, q - 1, r, 2)) % MOD;
}
// If R is required at the current position,
// the previous ball must be P or Q.
if (last == 2) {
ans = (ans + CountUtil(p, q, r - 1, 0)) % MOD;
ans = (ans + CountUtil(p, q, r - 1, 1)) % MOD;
}
// Store and return the result of this state.
dp[p, q, r, last] = (int)(ans % MOD);
return dp[p, q, r, last];
}
static int arrangeBalls(int p, int q, int r)
{
// Initialize the DP table with -1.
dp = new int[p + 1, q + 1, r + 1, 3];
// Fill the entire DP table with -1.
for (int i = 0; i <= p; i++) {
for (int j = 0; j <= q; j++) {
for (int k = 0; k <= r; k++) {
for (int l = 0; l < 3; l++) {
dp[i, j, k, l] = -1;
}
}
}
}
long ans = 0;
// The last ball can be P, Q, or R.
ans = (ans + CountUtil(p, q, r, 0)) % MOD;
ans = (ans + CountUtil(p, q, r, 1)) % MOD;
ans = (ans + CountUtil(p, q, r, 2)) % MOD;
return (int)ans;
}
public static void Main()
{
int p = 1, q = 1, r = 1;
int res = arrangeBalls(p, q, r);
Console.WriteLine(res);
}
}
function countUtil(p, q, r, last, dp, MOD)
{
// If any count becomes negative, this arrangement
// is not possible.
if (p < 0 || q < 0 || r < 0)
return 0n;
// If only one P ball is remaining and P is required
// at the last position, there is exactly one way.
if (p === 1 && q === 0 && r === 0 && last === 0)
return 1n;
// If only one Q ball is remaining and Q is required
// at the last position, there is exactly one way.
if (p === 0 && q === 1 && r === 0 && last === 1)
return 1n;
// If only one R ball is remaining and R is required
// at the last position, there is exactly one way.
if (p === 0 && q === 0 && r === 1 && last === 2)
return 1n;
// If this state has already been calculated,
// return the stored result.
if (dp[p][q][r][last] !== -1n)
return dp[p][q][r][last];
let ans = 0n;
// If P is required at the current position,
// the previous ball must be Q or R.
if (last === 0) {
ans = (ans + countUtil(p - 1, q, r, 1, dp, MOD))
% MOD;
ans = (ans + countUtil(p - 1, q, r, 2, dp, MOD))
% MOD;
}
// If Q is required at the current position,
// the previous ball must be P or R.
if (last === 1) {
ans = (ans + countUtil(p, q - 1, r, 0, dp, MOD))
% MOD;
ans = (ans + countUtil(p, q - 1, r, 2, dp, MOD))
% MOD;
}
// If R is required at the current position,
// the previous ball must be P or Q.
if (last === 2) {
ans = (ans + countUtil(p, q, r - 1, 0, dp, MOD))
% MOD;
ans = (ans + countUtil(p, q, r - 1, 1, dp, MOD))
% MOD;
}
// Store and return the result of this state.
dp[p][q][r][last] = ans % MOD;
return dp[p][q][r][last];
}
function arrangeBalls(p, q, r)
{
const MOD = 1000000007n;
// Initialize the DP table with -1.
const dp = Array.from(
{length : p + 1},
() => Array.from(
{length : q + 1},
() => Array.from({length : r + 1},
() => Array(3).fill(-1n))));
let ans = 0n;
// The last ball can be P, Q, or R.
ans = (ans + countUtil(p, q, r, 0, dp, MOD)) % MOD;
ans = (ans + countUtil(p, q, r, 1, dp, MOD)) % MOD;
ans = (ans + countUtil(p, q, r, 2, dp, MOD)) % MOD;
return Number(ans);
}
// Driver code
let p = 1;
let q = 1;
let r = 1;
let res = arrangeBalls(p, q, r);
console.log(res);
Output
6
[Expected Approach] Using Bottom-Up DP(Tabulation) – O(p*q*r) Time and O(p*q*r) Space
The idea is to build the DP table iteratively. We define dp[p][q][r][last] as the number of valid arrangements using p, q, and r balls where the last ball is of type last. We start from the smallest states and gradually build larger states by adding a ball whose type is different from the previous one.
- Create a 4D DP table where dp[i][j][k][last] stores the number of valid arrangements using i, j, and k balls ending with last.
- Initialize the three single-ball states: P, Q, and R.
- For every state, calculate arrangements ending with P using states ending with Q or R.
- Similarly, calculate arrangements ending with Q from P or R, and ending with R from P or Q.
- Fill the table iteratively from smaller counts to larger counts.
- Add the three states dp[p][q][r][0], dp[p][q][r][1], and dp[p][q][r][2] to obtain the final answer.
#include <iostream>
#include <vector>
using namespace std;
const int MOD = 1000000007;
int arrangeBalls(int p, int q, int r)
{
// dp[i][j][k][last] stores the number of valid
// arrangements using i P balls, j Q balls and
// k R balls, where the last ball is of type
// P(0), Q(1), or R(2).
vector<vector<vector<vector<int>>>> dp(
p + 1, vector<vector<vector<int>>>(q + 1, vector<vector<int>>(r + 1, vector<int>(3, 0))));
// Base cases:
// A single ball can form a valid arrangement.
if (p >= 1)
dp[1][0][0][0] = 1;
if (q >= 1)
dp[0][1][0][1] = 1;
if (r >= 1)
dp[0][0][1][2] = 1;
// Build the DP table from smaller states
// to larger states.
for (int i = 0; i <= p; i++)
{
for (int j = 0; j <= q; j++)
{
for (int k = 0; k <= r; k++)
{
// Current state cannot be empty.
if (i + j + k == 0)
continue;
// If the last ball is P,
// we can add Q or R.
// Add Q.
if (dp[i][j][k][0] != 0 && j < q)
{
dp[i][j + 1][k][1] = (dp[i][j + 1][k][1] + dp[i][j][k][0]) % MOD;
}
// Add R.
if (dp[i][j][k][0] != 0 && k < r)
{
dp[i][j][k + 1][2] = (dp[i][j][k + 1][2] + dp[i][j][k][0]) % MOD;
}
// If the last ball is Q,
// we can add P or R.
// Add P.
if (dp[i][j][k][1] != 0 && i < p)
{
dp[i + 1][j][k][0] = (dp[i + 1][j][k][0] + dp[i][j][k][1]) % MOD;
}
// Add R.
if (dp[i][j][k][1] != 0 && k < r)
{
dp[i][j][k + 1][2] = (dp[i][j][k + 1][2] + dp[i][j][k][1]) % MOD;
}
// If the last ball is R,
// we can add P or Q.
// Add P.
if (dp[i][j][k][2] != 0 && i < p)
{
dp[i + 1][j][k][0] = (dp[i + 1][j][k][0] + dp[i][j][k][2]) % MOD;
}
// Add Q.
if (dp[i][j][k][2] != 0 && j < q)
{
dp[i][j + 1][k][1] = (dp[i][j + 1][k][1] + dp[i][j][k][2]) % MOD;
}
}
}
}
// The final arrangement can end with P, Q, or R.
long long ans = 0;
ans = (ans + dp[p][q][r][0]) % MOD;
ans = (ans + dp[p][q][r][1]) % MOD;
ans = (ans + dp[p][q][r][2]) % MOD;
return ans;
}
int main()
{
int p = 1, q = 1, r = 1;
int res = arrangeBalls(p, q, r);
cout << res << endl;
return 0;
}
import java.util.*;
class GFG {
static final int MOD = 1000000007;
static int arrangeBalls(int p, int q, int r)
{
// dp[i][j][k][last] stores the number of valid
// arrangements using i P balls, j Q balls and
// k R balls, where the last ball is of type
// P(0), Q(1), or R(2).
int[][][][] dp = new int[p + 1][q + 1][r + 1][3];
// Base cases:
// A single ball can form a valid arrangement.
if (p >= 1)
dp[1][0][0][0] = 1;
if (q >= 1)
dp[0][1][0][1] = 1;
if (r >= 1)
dp[0][0][1][2] = 1;
// Build the DP table from smaller states
// to larger states.
for (int i = 0; i <= p; i++) {
for (int j = 0; j <= q; j++) {
for (int k = 0; k <= r; k++) {
// Current state cannot be empty.
if (i + j + k == 0)
continue;
// If the last ball is P,
// we can add Q or R.
// Add Q.
if (dp[i][j][k][0] != 0 && j < q) {
dp[i][j + 1][k][1]
= (int)((dp[i][j + 1][k][1]
+ (long)dp[i][j][k][0])
% MOD);
}
// Add R.
if (dp[i][j][k][0] != 0 && k < r) {
dp[i][j][k + 1][2]
= (int)((dp[i][j][k + 1][2]
+ (long)dp[i][j][k][0])
% MOD);
}
// If the last ball is Q,
// we can add P or R.
// Add P.
if (dp[i][j][k][1] != 0 && i < p) {
dp[i + 1][j][k][0]
= (int)((dp[i + 1][j][k][0]
+ (long)dp[i][j][k][1])
% MOD);
}
// Add R.
if (dp[i][j][k][1] != 0 && k < r) {
dp[i][j][k + 1][2]
= (int)((dp[i][j][k + 1][2]
+ (long)dp[i][j][k][1])
% MOD);
}
// If the last ball is R,
// we can add P or Q.
// Add P.
if (dp[i][j][k][2] != 0 && i < p) {
dp[i + 1][j][k][0]
= (int)((dp[i + 1][j][k][0]
+ (long)dp[i][j][k][2])
% MOD);
}
// Add Q.
if (dp[i][j][k][2] != 0 && j < q) {
dp[i][j + 1][k][1]
= (int)((dp[i][j + 1][k][1]
+ (long)dp[i][j][k][2])
% MOD);
}
}
}
}
// The final arrangement can end with P, Q, or R.
long ans = 0;
ans = (ans + dp[p][q][r][0]) % MOD;
ans = (ans + dp[p][q][r][1]) % MOD;
ans = (ans + dp[p][q][r][2]) % MOD;
return (int)ans;
}
public static void main(String[] args)
{
int p = 1, q = 1, r = 1;
int res = arrangeBalls(p, q, r);
System.out.println(res);
}
}
def arrangeBalls(p, q, r):
MOD = 1000000007
# dp[i][j][k][last] stores the number of valid
# arrangements using i P balls, j Q balls and
# k R balls, where the last ball is of type
# P(0), Q(1), or R(2).
dp = [
[
[
[0] * 3
for _ in range(r + 1)
]
for _ in range(q + 1)
]
for _ in range(p + 1)
]
# Base cases:
# A single ball can form a valid arrangement.
if p >= 1:
dp[1][0][0][0] = 1
if q >= 1:
dp[0][1][0][1] = 1
if r >= 1:
dp[0][0][1][2] = 1
# Build the DP table from smaller states
# to larger states.
for i in range(p + 1):
for j in range(q + 1):
for k in range(r + 1):
# Current state cannot be empty.
if i + j + k == 0:
continue
# If the last ball is P,
# we can add Q or R.
# Add Q.
if dp[i][j][k][0] != 0 and j < q:
dp[i][j + 1][k][1] = (
dp[i][j + 1][k][1]
+ dp[i][j][k][0]
) % MOD
# Add R.
if dp[i][j][k][0] != 0 and k < r:
dp[i][j][k + 1][2] = (
dp[i][j][k + 1][2]
+ dp[i][j][k][0]
) % MOD
# If the last ball is Q,
# we can add P or R.
# Add P.
if dp[i][j][k][1] != 0 and i < p:
dp[i + 1][j][k][0] = (
dp[i + 1][j][k][0]
+ dp[i][j][k][1]
) % MOD
# Add R.
if dp[i][j][k][1] != 0 and k < r:
dp[i][j][k + 1][2] = (
dp[i][j][k + 1][2]
+ dp[i][j][k][1]
) % MOD
# If the last ball is R,
# we can add P or Q.
# Add P.
if dp[i][j][k][2] != 0 and i < p:
dp[i + 1][j][k][0] = (
dp[i + 1][j][k][0]
+ dp[i][j][k][2]
) % MOD
# Add Q.
if dp[i][j][k][2] != 0 and j < q:
dp[i][j + 1][k][1] = (
dp[i][j + 1][k][1]
+ dp[i][j][k][2]
) % MOD
# The final arrangement can end with P, Q, or R.
ans = 0
ans = (ans + dp[p][q][r][0]) % MOD
ans = (ans + dp[p][q][r][1]) % MOD
ans = (ans + dp[p][q][r][2]) % MOD
return ans
# Driver code
if __name__ == "__main__":
p = 1
q = 1
r = 1
res = arrangeBalls(p, q, r)
print(res)
using System;
class GFG {
const int MOD = 1000000007;
static int arrangeBalls(int p, int q, int r)
{
// dp[i][j][k][last] stores the number of valid
// arrangements using i P balls, j Q balls and
// k R balls, where the last ball is of type
// P(0), Q(1), or R(2).
int[, , , ] dp = new int[p + 1, q + 1, r + 1, 3];
// Base cases:
// A single ball can form a valid arrangement.
if (p >= 1)
dp[1, 0, 0, 0] = 1;
if (q >= 1)
dp[0, 1, 0, 1] = 1;
if (r >= 1)
dp[0, 0, 1, 2] = 1;
// Build the DP table from smaller states
// to larger states.
for (int i = 0; i <= p; i++) {
for (int j = 0; j <= q; j++) {
for (int k = 0; k <= r; k++) {
// Current state cannot be empty.
if (i + j + k == 0)
continue;
// If the last ball is P,
// we can add Q or R.
// Add Q.
if (dp[i, j, k, 0] != 0 && j < q) {
dp[i, j + 1, k, 1]
= (int)((dp[i, j + 1, k, 1]
+ (long)dp[i, j, k, 0])
% MOD);
}
// Add R.
if (dp[i, j, k, 0] != 0 && k < r) {
dp[i, j, k + 1, 2]
= (int)((dp[i, j, k + 1, 2]
+ (long)dp[i, j, k, 0])
% MOD);
}
// If the last ball is Q,
// we can add P or R.
// Add P.
if (dp[i, j, k, 1] != 0 && i < p) {
dp[i + 1, j, k, 0]
= (int)((dp[i + 1, j, k, 0]
+ (long)dp[i, j, k, 1])
% MOD);
}
// Add R.
if (dp[i, j, k, 1] != 0 && k < r) {
dp[i, j, k + 1, 2]
= (int)((dp[i, j, k + 1, 2]
+ (long)dp[i, j, k, 1])
% MOD);
}
// If the last ball is R,
// we can add P or Q.
// Add P.
if (dp[i, j, k, 2] != 0 && i < p) {
dp[i + 1, j, k, 0]
= (int)((dp[i + 1, j, k, 0]
+ (long)dp[i, j, k, 2])
% MOD);
}
// Add Q.
if (dp[i, j, k, 2] != 0 && j < q) {
dp[i, j + 1, k, 1]
= (int)((dp[i, j + 1, k, 1]
+ (long)dp[i, j, k, 2])
% MOD);
}
}
}
}
// The final arrangement can end with P, Q, or R.
long ans = 0;
ans = (ans + dp[p, q, r, 0]) % MOD;
ans = (ans + dp[p, q, r, 1]) % MOD;
ans = (ans + dp[p, q, r, 2]) % MOD;
return (int)ans;
}
public static void Main()
{
int p = 1, q = 1, r = 1;
int res = arrangeBalls(p, q, r);
Console.WriteLine(res);
}
}
function arrangeBalls(p, q, r)
{
const MOD = 1000000007n;
// dp[i][j][k][last] stores the number of valid
// arrangements using i P balls, j Q balls and
// k R balls, where the last ball is of type
// P(0), Q(1), or R(2).
const dp = Array.from({ length: p + 1 }, () =>
Array.from({ length: q + 1 }, () =>
Array.from({ length: r + 1 }, () =>
Array(3).fill(0n)
)
)
);
// Base cases:
// A single ball can form a valid arrangement.
if (p >= 1)
dp[1][0][0][0] = 1n;
if (q >= 1)
dp[0][1][0][1] = 1n;
if (r >= 1)
dp[0][0][1][2] = 1n;
// Build the DP table from smaller states
// to larger states.
for (let i = 0; i <= p; i++)
{
for (let j = 0; j <= q; j++)
{
for (let k = 0; k <= r; k++)
{
// Current state cannot be empty.
if (i + j + k === 0)
continue;
// If the last ball is P,
// we can add Q or R.
// Add Q.
if (dp[i][j][k][0] !== 0n && j < q)
{
dp[i][j + 1][k][1] =
(dp[i][j + 1][k][1]
+ dp[i][j][k][0]) % MOD;
}
// Add R.
if (dp[i][j][k][0] !== 0n && k < r)
{
dp[i][j][k + 1][2] =
(dp[i][j][k + 1][2]
+ dp[i][j][k][0]) % MOD;
}
// If the last ball is Q,
// we can add P or R.
// Add P.
if (dp[i][j][k][1] !== 0n && i < p)
{
dp[i + 1][j][k][0] =
(dp[i + 1][j][k][0]
+ dp[i][j][k][1]) % MOD;
}
// Add R.
if (dp[i][j][k][1] !== 0n && k < r)
{
dp[i][j][k + 1][2] =
(dp[i][j][k + 1][2]
+ dp[i][j][k][1]) % MOD;
}
// If the last ball is R,
// we can add P or Q.
// Add P.
if (dp[i][j][k][2] !== 0n && i < p)
{
dp[i + 1][j][k][0] =
(dp[i + 1][j][k][0]
+ dp[i][j][k][2]) % MOD;
}
// Add Q.
if (dp[i][j][k][2] !== 0n && j < q)
{
dp[i][j + 1][k][1] =
(dp[i][j + 1][k][1]
+ dp[i][j][k][2]) % MOD;
}
}
}
}
// The final arrangement can end with P, Q, or R.
let ans = 0n;
ans = (ans + dp[p][q][r][0]) % MOD;
ans = (ans + dp[p][q][r][1]) % MOD;
ans = (ans + dp[p][q][r][2]) % MOD;
return Number(ans);
}
// Driver code
let p = 1;
let q = 1;
let r = 1;
let res = arrangeBalls(p, q, r);
console.log(res);
Output
6