📌  相关文章
📜  元素最多为 K 的不同 N 大小数组的计数,以便相邻元素对是升序或非倍数

📅  最后修改于: 2021-10-26 06:01:40             🧑  作者: Mango

给定两个整数NK ,找出创建 N 个元素数组的不同方法,其中每个元素都在[1, K]范围内,并且每对相邻元素 (P, Q) 使得P <= QP % Q > 0

例子:

方法:根据以下观察,可以使用动态规划解决给定的问题:

  • 考虑一个二维数组,比如dp[][]其中dp[x][y]表示长度为 x的数组的计数,其中y作为它们的最后一个元素。
  • 现在,创建一个长度为 x的数组的方法的数量,其中y作为它们的最后一个元素,并且所有数组元素都在[1, K]范围内是创建一个长度为 (y – 1)的数组的方法的总和,其具有范围 [1, K]上的最后一个元素,可以表示为关系dp[x][y] = \sum_{j=1}^{j = k} dp[x-1][j]      .
  • 仅考虑P <= QP % Q > 0 的情况,其中 (P, Q) 是相邻元素对。可以使用关系从每个状态中减去不满足这些条件之一的数组dp[x][y] = \sum_{j=1}^{j = k} dp[x-1][j]      是其中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 <= QP % Q > 0的情况。
  • 完成以上步骤后,打印值 \sum_{j=1}^{j = k} dp[N][j]      作为结果。

下面是上述方法的实现:

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 现场工作专业课程学生竞争性编程现场课程。