P4071 [SDOI2016]排列计数

题目地址

题目大意:求\(n\)的错位排序数

有全排列\(1\sim n,\left \{ 1,2,3,\dots ,n\right \}\)对于\(a[i]\ne i\)
我们称为错位排列
有递推式

\[D_n = (n-1)(D_{n-1} + D_{n-2}) \]

证明:
设有\(n\)的全排列\(\left\{1,2,3,4, \dots n \right \}\)
\(n = 1\)\(D_n\)为0
\(n = 2\)\(D_n\)为1
设最后1位为\(x_n\)
\(n(n>2),k(k \ne n)\)n在第\(k\)

  1. \(k\)\(n\)上有 \(D_{(n-2)}\)种错排
  2. \(k\)不排在第\(n\)位时,那么将第\(n\)位重新考虑成一个新的“第\(k\)位”,这时的包括\(k\)在内的剩下\(n-1\)个数的每一种错排,都等价于只有\(n-1\)个数时的错排(只是其中的第\(k\)位会换成第\(n\)位)。其错排数为\(D_{n-1}\)
    因为\(k\)\(n-1\)种取法所以\(D_n = (n-1)(D_{n-1} + D_{n-2})\)
#include <iostream>

using namespace std;

typedef long long ll;
ll f[25];
int main()
{
    int n;
    scanf("%d",&n);
    f[1] = 0,f[2] = 1;
    for(int i = 3 ; i <= n ; i ++ )
    {
        f[i] = (i - 1)*(f[i - 1] + f[i - 2]);
    }
    printf("%lld",f[n]);
}

然后我们就可写下面一道题了 [SDOI2016]排列计数

求有多少种 \(1\)\(n\) 的排列 \(a\),满足序列恰好有 \(m\) 个位置 \(i\),使得 \(a_i = i\)
答案对 \(10^9 + 7\) 取模。

题目大意:
题意是让长度为n的序列有且仅有有m个数在原本的位置上.

也就是求除\(n-m\)的错位排序数乘上\(m\)个数的位置\(C^n_m\)
\(C^n_m \times D_{n-m}\)

通过预处理阶乘逆元和错位排序数,在进行查表操作即可

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

typedef long long ll;

const int N = 1000010;
const int mod = 1e9 + 7;
ll db[N];
ll invfact[N],fact[N];


int power(int a,int b,int p)
{
    int res = 1;
    while(b)
    {
        if(b&1)res = (ll)res * a % p;
        a = (ll) a * a % p;
        b >>= 1;
    }
    return res;
}

void facts()
{
    fact[0] = invfact[0] = 1;
    for(int i = 1 ; i <= N ; i ++ )
    {
        fact[i] = (ll)fact[i - 1] * i % mod;
        invfact[i] = (ll)invfact[i - 1] * power(i,mod - 2,mod) % mod;
    }
}


void dbs()
{
    db[1] = 0,db[2] = 1;
    for(int i = 3 ; i <= N ; i ++ )
    {
        db[i] =(i - 1)*(db[i - 1] + db[ i - 2 ]) % mod;
    }
}




int main()
{
    
    int T,n,m;
    scanf("%d",&T);
    facts();
    dbs();
    while(T--)
    {
        scanf("%d%d",&n,&m);
        if(n == m){printf("1\n");continue;}
                    
        ll cnm = (ll)fact[n] * invfact[m] % mod * invfact[n - m] % mod;
        printf("%lld\n",(ll)cnm * db[n-m]%mod);

    }

}
posted @ 2022-07-13 13:30  Erfu  阅读(56)  评论(0)    收藏  举报