给定N个整数的数组arr []以及整数M,L,R 。考虑变量S (最初为0 )。对给定数组中的每个元素执行以下操作后,任务是找到位于[L,R]范围内的S%M值的最大数量:
- 在S中添加arr [i]或arr [i] – 1 。
- 将S更改为S%M 。
例子:
Input: arr[] = {17, 11, 10, 8, 15}, M = 22, L = 14, R = 16
Output: 3
Explanation:
Initially S = 0,
Step 1: Choose, arr[0] – 1 = 16 and add it to S = 16 and S%M = 16. Therefore, count = 1
Step 2: Choose, arr[1] = 11 and add it to S = 16 + 11 = 27 and S%M = 5. Therefore, count = 1
Step 3: Choose, arr[2] = 10 and add it to S = 16 + 10 +11 = 37 and S%M = 15. Therefore, count = 2
Step 4: Choose, arr[3] = 8 and add it to S = 16 + 10 + 11 + 8 = 45 and S%M = 1. Therefore, count = 2
Step 5: Choose, arr[4] = 15 and add it to S = 16 + 10 + 11 + 8 + 15 = 60 and S%M = 16. Therefore, count = 3.
Hence the maximum count is 3.
Input: arr[] = {23, 1}, M = 24, L = 21, R = 23
Output: 2
天真的方法:最简单的方法是遍历给定的数组arr []并将arr [i]或arr [i – 1]添加到给定的S中,并检查S%M是否在[L,R]范围内。由于有两种可能性来选择给定的数字。因此,使用递归来递归地获取S%M的最大值在[L,R]范围内。
时间复杂度: O(2 N )
辅助空间: O(N)
高效的方法:为了优化上述方法,其思想是使用动态编程存储重叠的子问题,然后找到S%M的最大数量在[L,R]范围内。请按照以下步骤解决问题:
- 初始化unordered_map dp以存储具有重叠子问题的状态的值。
- 将总和初始化为0 ,然后将arr [i]或arr [i] – 1值递归加到总和S上。
- 在每个步骤中,检查S%M是否在[L,R]范围内。如果它在该范围内,则计算该值并在上面的映射dp中将此当前状态更新为1。否则将其更新为0 。
- 查找所有可能的组合后,返回位于[L,R]范围内的S%M的值的计数。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Lookup table
map, int> dp;
// Function to count the value of S
// after adding arr[i] or arr[i - 1]
// to the sum S at each time
int countMagicNumbers(int idx, int sum,
int a[], int n,
int m, int l, int r)
{
// Base Case
if (idx == n) {
// Store the mod value
int temp = sum % m;
// If the mod value lies in
// the range then return 1
if (temp == l || temp == r
|| (temp > l && temp < r))
return dp[{ idx, sum }] = 1;
// Else return 0
else
return dp[{ idx, sum }] = 0;
}
// Store the current state
pair curr
= make_pair(idx, sum);
// If already computed, return the
// computed value
if (dp.find(curr) != dp.end())
return dp[curr];
// Recursively adding the elements
// to the sum adding ai value
int ls = countMagicNumbers(idx + 1,
sum + a[idx],
a, n,
m, l, r);
// Adding arr[i] - 1 value
int rs = countMagicNumbers(idx + 1,
sum + (a[idx] - 1),
a, n, m, l, r);
// Return the maximum count to
// check for root value as well
int temp1 = max(ls, rs);
int temp = sum % m;
// Avoid counting idx = 0 as possible
// solution we are using idx != 0
if ((temp == l || temp == r
|| (temp > l && temp < r))
&& idx != 0) {
temp1 += 1;
}
// Return the value of current state
return dp[{ idx, sum }] = temp1;
}
// Driver Code
int main()
{
int N = 5, M = 22, L = 14, R = 16;
int arr[] = { 17, 11, 10, 8, 15 };
cout << countMagicNumbers(0, 0, arr,
N, M, L, R);
return 0;
}
Python3
# Python3 program for the above approach
# Lookup table
dp = {}
# Function to count the value of S
# after adding arr[i] or arr[i - 1]
# to the sum S at each time
def countMagicNumbers(idx, sum, a, n, m, l, r):
# Base Case
if (idx == n):
# Store the mod value
temp = sum % m
# If the mod value lies in
# the range then return 1
if (temp == l or temp == r or
(temp > l and temp < r)):
dp[(idx, sum)] = 1
return dp[(idx, sum)]
# Else return 0
else:
dp[(idx, sum)] = 0
return dp[(idx, sum)]
# Store the current state
curr = (idx, sum)
# If already computed, return the
# computed value
if (curr in dp):
return dp[curr]
# Recursively adding the elements
# to the sum adding ai value
ls = countMagicNumbers(idx + 1,
sum + a[idx],
a, n, m, l, r)
# Adding arr[i] - 1 value
rs = countMagicNumbers(idx + 1,
sum + (a[idx] - 1),
a, n, m, l, r)
# Return the maximum count to
# check for root value as well
temp1 = max(ls, rs)
temp = sum % m
# Avoid counting idx = 0 as possible
# solution we are using idx != 0
if ((temp == l or temp == r or
(temp > l and temp < r)) and
idx != 0):
temp1 += 1
# Return the value of current state
dp[(idx, sum)] = temp1
return dp[(idx, sum)]
# Driver Code
if __name__ == '__main__':
N = 5
M = 22
L = 14
R = 16
arr = [ 17, 11, 10, 8, 15 ]
print(countMagicNumbers(0, 0, arr, N, M, L, R))
# This code is contributed by mohit kumar 29
3
时间复杂度: O(S * N),其中N是给定数组的大小,而S是所有数组元素的总和。
空间复杂度: O(S * N)