给定两个整数N和K ,找出创建 N 个元素数组的不同方法,其中每个元素都在[1, K]范围内,并且每对相邻元素 (P, Q) 使得P <= Q或P % Q > 0 。
例子:
Input: N = 2, K = 3
Output: 7
Explantation: The arrays that satisfies the given conditions are {1, 1}, {1, 2}, {1, 3}, {2, 2}, {2, 3}, {3, 3}, {3, 2}.
Input: N = 9, K = 1
Output: 1
Explaination: : The only arrays that satisfies the given conditions is {1, 1, 1, 1, 1, 1, 1, 1, 1}.
方法:根据以下观察,可以使用动态规划解决给定的问题:
- 考虑一个二维数组,比如dp[][]其中dp[x][y]表示长度为 x的数组的计数,其中y作为它们的最后一个元素。
- 现在,创建一个长度为 x的数组的方法的数量,其中y作为它们的最后一个元素,并且所有数组元素都在[1, K]范围内是创建一个长度为 (y – 1)的数组的方法的总和,其具有范围 [1, K]上的最后一个元素,可以表示为关系 .
- 仅考虑P <= Q或P % Q > 0 的情况,其中 (P, Q) 是相邻元素对。可以使用关系从每个状态中减去不满足这些条件之一的数组是其中y % j = 0 。
根据上述观察,计算 dp[][] 表并打印dp[N][K] 的值作为所形成数组的结果计数。请按照以下步骤解决给定的问题:
- 使用 Sieve of Eratosthenes 中的方法将范围 [1, K]内所有整数的所有除数存储在一个数组中,例如 divisor[][] 。
- 初始化一个二维数组,比如维度为(N + 1)*(K + 1) 的dp[][] ,这样dp[x][y]表示长度为 x的数组的计数,其中y作为它们的最后一个元素。
- 将dp[1][j]初始化为1作为创建大小为 1的数组的方法数,该数组将任何元素j作为其最后一个元素为1 。
- 使用变量x在范围[2, N] 上迭代并执行以下步骤:
- 对于 [1, K]范围内j 的每个可能值,将 dp[x][y]的值增加dp[x – 1][j] 。
- 使用 y的值对范围[1, K]进行迭代,对于每个除数,假设y 的D 将 dp[x][y]的值递减dp[x – 1][D],因为这不满足对于所有相邻元素(P, Q) 的P <= Q或P % Q > 0的情况。
- 完成以上步骤后,打印值作为结果。
下面是上述方法的实现:
C++
// C++ program of the above approach
#include
using namespace std;
// Function to find the count of distinct
// arrays of size n having elements in
// range [1, k] and all adjacent elements
// (P, Q) follows (P <= Q) or (P % Q > 0)
int countArrays(int n, int k)
{
// Stores the divisors of all
// integers in the range [1, k]
vector > divisors(k + 1);
// Calculate the divisors of all
// integers using the Sieve
for (int i = 1; i <= k; i++) {
for (int j = 2 * i; j <= k; j += i) {
divisors[j].push_back(i);
}
}
// Stores the dp states such that
// dp[i][j] with i elements having
// j as the last element of array
vector > dp(
n + 1, vector(k + 1));
// Initialize the dp array
for (int j = 1; j <= k; j++) {
dp[1][j] = 1;
}
// Calculate the dp states using the
// derived relation
for (int x = 2; x <= n; x++) {
// Calculate the sum for len-1
int sum = 0;
for (int j = 1; j <= k; j++) {
sum += dp[x - 1][j];
}
// Subtract dp[len-1][j] for each
// factor of j from [1, K]
for (int y = 1; y <= k; y++) {
dp[x][y] = sum;
for (int d : divisors[y]) {
dp[x][y] = (dp[x][y] - dp[x - 1][d]);
}
}
}
// Calculate the final result
int sum = 0;
for (int j = 1; j <= k; j++) {
sum += dp[n][j];
}
// Return the resultant sum
return sum;
}
// Driver Code
int main()
{
int N = 2, K = 3;
cout << countArrays(N, K);
return 0;
}
Javascript
输出
7
时间复杂度: O(N*K*log K)
辅助空间: O(K*log K)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。