使用 C++ 计算重遇数(计数部分错排)
给定两个整数 N 和 k,我们需要计算 k 个点固定在其位置的错排数。给定 k 的约束条件在 0 到 n 之间,因为当有 n 个点时,固定点的数量不能超过 n。
int N=4, k=2; res = solve(N, k);
请注意,k 上至少条件不成立。必须精确且严格地有 k 个点在其原始索引上。这是一个数学问题。我们不解释数学的证明和解释,作为计算机科学专业的学生,我们可以使用数学家形成的结果。结果是,𝑹𝒆𝒄𝒐𝒏𝒕𝒓𝒆𝒔(𝒏, 𝒌) = 𝒏𝑪𝒌 ∗ 𝑹𝒆𝒄𝒐𝒏𝒕𝒓𝒆𝒔(𝒏− 𝒌, 𝟎)
让我们来看一些输入/输出场景
假设 N 个点作为输入,其中没有分配固定点。获得的结果值将是所有点的组合 -
Input: N = 4, k = 0 Result: 9
使用任何四个坐标点,在没有任何固定点的情况下,我们可以获得 9 种不同的组合。
假设 N 个点作为输入,其中所有点都已固定。获得的结果值将是所有点的组合 -
Input: N = 4, k = 4 Result: 1
如果所有点都固定,则只获得一个结果组合。
算法
该算法的基本思想源于各种轴上坐标点的排列和组合的思想。因此,它用于识别在一张图上绘制一组点的几种方式。
将点数和固定点数作为方法的输入。
我们应用组合公式来查找不同的组合
如果没有输入,程序返回 1。
如果没有固定点和一个坐标,程序返回 0。
如果没有固定点,程序将递归调用以查找所有组合,同时更改所有坐标的位置。
如果有固定点,则应用组合公式
示例
例如,让我们考虑 N=3,k=1;因此,只有一个点必须在其原始索引上。
如果给定的点是 {1,3,2}、{3,2,1}、{2,1,3},以下是用 C++ 编写的实现重遇数的程序,其中我们计算指定固定点的排列数 -
#include <iostream> using namespace std; int nCr(int n, int r) { if (r==0 || r==n) return 1; return nCr(n-1, r-1) + nCr(n-1, r); } int solve(int N, int k) { if (N==0 && k==0) return 1; if (N==1 && k==0) return 0; if (k==0) return (N-1) * (solve(N-1, 0) + solve(N-2, 0)); return nCr(N, k) * solve(N-k, 0); } int main() { int N=3, k=1; cout << solve(N, k); return 0; }
输出
3
结论
我们使用先前结果使用 DP 存储最后一个值以进行更快的处理。此外,为了找到 nCr,我们可以使用一种优化的方法。
广告