Given three integers n,l,r, the task is to determine the count of such arrays that follow the below two conditions:
- All the elements of the array are between l to r (inclusive)
- The sum of all the elements is divisible by 3.
Since the answer can be very long, print the remainder when the result is divided by 1e9+7.
Example:
Input: n=2, l=1, r=3
Output: 3 1
Explanation: [1,2][2,1][3,3]Input: n = 3, l = 2, r = 2
Output: 1
Approach:
The intuition behind the solution is based on modular arithmetic and dynamic programming.
Here’s a detailed explanation:
Modular Arithmetic: Since we need the sum of the array to be divisible by 3, we don’t care about the actual numbers themselves, but their remainder when divided by 3. This means we’re interested in how many numbers x exists such that x mod 3 equals 0, 1, or 2. We can count these numbers using simple formulas. For example, to count the number of x with a remainder of 1 when divided by 3 (i.e., x = 3k + 1 for some integer k), we can create an inequality l ≤ 3k + 1 ≤ r, simplify it to ceil((l-1)/3) ≤ k ≤ floor((r-1)/3), and then count the number of such k.
Dynamic Programming: After counting all the numbers, we can solve the problem using dynamic programming. We define dp[i][j] as the number of ways to form an array with i numbers such that the sum of these numbers modulo 3 equals j. There are O(n) states (since i can range from 0 to n and j can range from 0 to 2), and we can transition between states by adding a number to the array. The final answer will be at dp[n][0], which represents the number of ways to form an array of length n such that the sum of the numbers is divisible by 3.
The recurrence relation is:
dp[i][(j + k) % 3] = (dp[i][(j + k) % 3] + dp[i – 1][j] * cnt[k]) % MOD
This recurrence relation is used to fill the dynamic programming table dp. Here’s what it represents:
- dp[i][(j + k) % 3] is the current state, representing the number of arrays of length i where the sum of the elements has a remainder of (j + k) % 3 when divided by 3.
- dp[i][(j + k) % 3] is updated by adding the number of arrays of length i – 1 where the sum of the elements has a remainder of j when divided by 3, multiplied by the count of numbers that have a remainder of k when divided by 3 (cnt[k]).
Steps-by-step approach:
- Initialize an array cnt to count the numbers between l and r with remainders 0, 1, and 2 when divided by 3.
- Create a 2D array dp to store intermediate results. Set dp[0][0] = 1 as the base case, this represents the base case where there are no elements in the array and the sum is 0.
-
Fill DP Table:
- Iterate over the array length and remainders using nested loops.
- For each position, calculate possible remainders of the sum based on the previous position and the counts of numbers with different remainders in the range.
- Update the DP table based on the recurrence relation.
- Print dp[n][0], representing the number of arrays where the sum of elements is divisible by 3.
Below is the implementation of the above approach:
#include <bits/stdc++.h> using namespace std;
// Define the modulus for the problem const int MOD = 1e9 + 7;
// Initialize the dynamic programming table and the count // array long long dp[200005][3], cnt[3];
void solve( int n, int l, int r)
{ // Count the numbers between l and r that have a
// remainder of 0, 1, or 2 when divided by 3
for ( int i = 0; i < 3; ++i) {
cnt[i] = (r - i + 3) / 3 - (l - 1 - i + 3) / 3;
}
// Initialize the dynamic programming table
dp[0][0] = 1;
// Fill the dynamic programming table
for ( int i = 1; i <= n; ++i) {
for ( int j = 0; j < 3; ++j) {
for ( int k = 0; k < 3; ++k) {
dp[i][(j + k) % 3]
= (dp[i][(j + k) % 3]
+ 1LL * dp[i - 1][j] * cnt[k])
% MOD;
}
}
}
// Print the number of arrays where the sum of the
// elements is divisible by 3
cout << dp[n][0] << endl;
} int main()
{ // Variables for the length of the array and the range
// of the elements
long long n = 2, l = 1, r = 3;
solve(n,l,r);
return 0;
} |
public class GFG {
// Define the modulus for the problem
private static final int MOD = 1000000007 ;
// Initialize the dynamic programming table and the count array
private static long [][] dp = new long [ 200005 ][ 3 ];
private static long [] cnt = new long [ 3 ];
private static void solve( long n, long l, long r) {
// Count the numbers between l and r that have a
// remainder of 0, 1, or 2 when divided by 3
for ( int i = 0 ; i < 3 ; ++i) {
cnt[i] = (r - i + 3 ) / 3 - (l - 1 - i + 3 ) / 3 ;
}
// Initialize the dynamic programming table
dp[ 0 ][ 0 ] = 1 ;
// Fill the dynamic programming table
for ( int i = 1 ; i <= n; ++i) {
for ( int j = 0 ; j < 3 ; ++j) {
for ( int k = 0 ; k < 3 ; ++k) {
dp[i][(j + k) % 3 ] = (dp[i][(j + k) % 3 ]
+ (dp[i - 1 ][j] * cnt[k]) % MOD) % MOD;
}
}
}
// Print the number of arrays where the sum of the
// elements is divisible by 3
System.out.println(dp[( int ) n][ 0 ]);
}
public static void main(String[] args) {
// Variables for the length of the array and the range
// of the elements
long n = 2 , l = 1 , r = 3 ;
solve(n, l, r);
}
} |
# Define the modulus for the problem MOD = 10 * * 9 + 7
# Initialize the dynamic programming table and the count array dp = [[ 0 ] * 3 for _ in range ( 200005 )]
cnt = [ 0 ] * 3
def solve(n, l, r):
global dp, cnt
# Count the numbers between l and r that have a remainder
# of 0, 1, or 2 when divided by 3
for i in range ( 3 ):
cnt[i] = (r - i + 3 ) / / 3 - (l - 1 - i + 3 ) / / 3
# Initialize the dynamic programming table
dp[ 0 ][ 0 ] = 1
# Fill the dynamic programming table
for i in range ( 1 , n + 1 ):
for j in range ( 3 ):
for k in range ( 3 ):
dp[i][(j + k) % 3 ] = (dp[i][(j + k) % 3 ] + dp[i - 1 ][j] * cnt[k]) % MOD
# Print the number of arrays where the sum of the elements is divisible by 3
print (dp[n][ 0 ])
if __name__ = = "__main__" :
# Variables for the length of the array and the range of the elements
n = 2
l = 1
r = 3
solve(n, l, r)
|
using System;
public class GFG
{ // Define the modulus for the problem
private const int MOD = 1000000007;
// Initialize the dynamic programming table and the count array
private static long [,] dp = new long [200005, 3];
private static long [] cnt = new long [3];
private static void Solve( long n, long l, long r)
{
// Count the numbers between l and r that have a
// remainder of 0, 1, or 2 when divided by 3
for ( int i = 0; i < 3; ++i)
{
cnt[i] = (r - i + 3) / 3 - (l - 1 - i + 3) / 3;
}
// Initialize the dynamic programming table
dp[0, 0] = 1;
// Fill the dynamic programming table
for ( int i = 1; i <= n; ++i)
{
for ( int j = 0; j < 3; ++j)
{
for ( int k = 0; k < 3; ++k)
{
dp[i, (j + k) % 3] = (dp[i, (j + k) % 3]
+ (dp[i - 1, j] * cnt[k]) % MOD) % MOD;
}
}
}
// Print the number of arrays where the sum of the
// elements is divisible by 3
Console.WriteLine(dp[n, 0]);
}
public static void Main( string [] args)
{
// Variables for the length of the array and the range
// of the elements
long n = 2, l = 1, r = 3;
Solve(n, l, r);
}
} |
const MOD = 1e9 + 7; // Function to solve the problem function GFG(n, l, r) {
// Initialize the dynamic programming table and count array
let dp = new Array(200005).fill(0).map(() => new Array(3).fill(0));
let cnt = Array(3).fill(0);
for (let i = 0; i < 3; ++i) {
cnt[i] = Math.floor((r - i + 3) / 3) - Math.floor((l - 1 - i + 3) / 3);
}
// Initialize the dynamic programming table
dp[0][0] = 1;
// Fill the dynamic programming table
for (let i = 1; i <= n; ++i) {
for (let j = 0; j < 3; ++j) {
for (let k = 0; k < 3; ++k) {
dp[i][(j + k) % 3] = (dp[i][(j + k) % 3] + (dp[i - 1][j] * cnt[k]) % MOD) % MOD;
}
}
}
// Print the number of the arrays where the sum of elements is divisible by 3
console.log(dp[n][0]);
} // Main function function main() {
// Variables for the length of the array and the range ofelements
let n = 2, l = 1, r = 3;
GFG(n, l, r);
} main(); |
3
Time Complexity: O(n)
Auxiliary Space: O(n)