错位排列

错位排列

一、错位排列:

1、定义:指没有任何元素出现在有序位置的排列,即对于长度为 \(n\) 的数组 \(a\),如果满足所有的 \(P_i \ne a_i\),则称 \(P\) 为数组 \(a\) 的错位排列。

2、利用容斥原理解决:

  • 令集合 \(S_i\) 表示满足 \(P_i \ne a_i\) 的排列数目,\(U\) 为全集。

  • 属性:\(P_i \ne a_i\)

3、那么最终的公式为:\(D_n=n!-n!\sum_{k=1}^{n}\frac{(-1)^{k-1}}{k!}=n!\sum_{k=0}^{n}\frac{(-1)^k}{k!}\)

4、错列排列的前几项为:\(0,1,2,9,44,265...\)

5、递推式:\(D_n=(n-1)(D_{n-1}+D_{n-2})\),另递推式:\(D_n=nD_{n-1}+(-1)^n\)

6、错列排序的简单表达式:\(D_n=\left \lfloor \frac{n!}{e} \right \rfloor = \left \lfloor \frac{n!}{e}+\frac{1}{2} \right \rfloor\)。(四舍五入)

7、另外可以推广到:

如果问你长度为 \(n\) 的数组 \(a\),如果保证 \(m\) 个位置稳定,即 \(P_i=a_i\),那么公式则为:\(D_{n}^{m}=C_{n}^{m}D_{n-m}\)

template<typename T>
struct C_per{
    int N;
    vector<T> D;
    C_per(int N_, T p = 1e9 + 7) : D(N_ + 1) {
        N = N_;
        D[1] = 0;
        D[2] = 1;
        for (T i = 2; i <= N; i++) {
            D[i] = (i - 1) * (D[i - 1] + D[i - 2]) % p;
        }
    }
    
    inline T get(T n) {
		return D[n];
	}
};

另外推广的代码:

template<typename T>
struct C_fi{
    inline T qp(T a, T b, T p = 1e9 + 7) {
		i64 res = 1;
		a %= p;
		for (; b; b >>= 1LL, a = 1LL * a * a % p) {
			if (b & 1) res = res * a % p;
		}
		return res;
	}
	
	inline T get_inv(T a, T p = 1e9 + 7) {
		return qp(a, p - 2, p);
	}
    
	int N;
	vector<T> fac, inv;
    C_fi() {}
	C_fi(int N_, T p = 1e9 + 7) : fac(N_ + 1), inv(N_ + 1) {
        N = N_;
        fac[0] = 1;
		for (T i = 1; i <= N; i++) fac[i] = 1LL * fac[i - 1] * i % p;
		inv[N] = get_inv(fac[N], p);
		for (T i = N - 1; i >= 1; i--) inv[i] = 1LL * inv[i + 1] * (i + 1) % p;
    }
	
	inline T C(T n, T m, T p = 1e9 + 7) {
		if (n < m) {
			return (T)0;
		}
		return fac[n] * inv[n - m] % p * inv[m] % p;
	}
};

template<typename T>
struct C_per{
    int N;
    C_fi st;
    vector<T> D;
    C_per(int N_, T p = 1e9 + 7) : D(N_ + 1) {
        N = N_;
        D[1] = 0;
        D[2] = 1;
        for (T i = 2; i <= N; i++) {
            D[i] = (i - 1) * (D[i - 1] + D[i - 2]) % p;
        }
        st = C_fi<T>(N, p);
    }
    
    inline T get(T n, T m, T p = 1e9 + 7) {
		if (n < m) {
			return (T)0;
		}
		return st.C(n, m, p) * D[n - m] % p;
	}
};
posted @ 2024-09-09 17:56  grape_king  阅读(193)  评论(0)    收藏  举报