组合数学+错排问题【p4071】[SDOI2016]排列计数

Description

求有多少种长度为 n 的序列 A,满足以下条件:

1 ~ n 这 n 个数在序列中各出现了一次

若第 i 个数 A[i] 的值为 i,则称 i 是稳定的。序列恰好有 m 个数是稳定的

满足条件的序列可能很多,序列数对 10^9+7109+7 取模。

Input

第一行一个数 T,表示有 T 组数据。

接下来 T 行,每行两个整数 n、m。

Output

输出 T 行,每行一个数,表示求出的序列数

组合数+错排问题。

预处理\(fac[i]\)代表\(i\)的阶乘.\(inv[i]\)代表\(i\)的阶乘的逆元。

\(f[i]\)代表有\(i\)个数的错排方案数。

我们的答案就是\(C_n^{m} \times f[n-m]\)

不难理解的解释.

注意判断\(n==m\)输出\(1\)。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#define int long long
#define mod 1000000007
#define R register

using namespace std;

const int gz=1000008;

int fac[gz]={1,1},inv[gz],T,f[gz];

inline void in(int &x)
{
    int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}

inline int ksm(R int x,R int y)
{
    R int res=1;
    for(;y;y>>=1,x=x*x%mod)
        if(y&1)res=res*x%mod;
    return res;
}

inline int C(R int n,R int m)
{
    return (fac[n]%mod*inv[n-m])%mod*(inv[m])%mod;
}

signed main()
{
    f[2]=1;
    for(R int i=2;i<=gz;i++)fac[i]=fac[i-1]*i%mod;
    inv[gz]=ksm(fac[gz],mod-2);
    for(R int i=gz-1;i>=0;i--)inv[i]=((i+1)*inv[i+1])%mod;
    for(R int i=3;i<=gz;i++)f[i]=(i-1)*(f[i-2]+f[i-1])%mod;
    in(T);
    for(R int n,m;T;T--)
    {
        in(n),in(m);
        if(n==m)puts("1");
        else printf("%lld\n",((C(n,m)%mod)*(f[n-m]%mod))%mod);
    }
}

原文地址:https://www.cnblogs.com/-guz/p/9892404.html

时间: 2024-11-05 14:59:02

组合数学+错排问题【p4071】[SDOI2016]排列计数的相关文章

BZOJ 4517: [Sdoi2016]排列计数 错排+逆元

4517: [Sdoi2016]排列计数 Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7 取模. Input 第一行一个数 T,表示有 T 组数据. 接下来 T 行,每行两个整数 n.m. T=500000,n≤1000000,m≤1000000 Output 输出 T 行,每行一个数,表示

【BZOJ4517】[Sdoi2016]排列计数 组合数+错排

[BZOJ4517][Sdoi2016]排列计数 Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7 取模. Input 第一行一个数 T,表示有 T 组数据. 接下来 T 行,每行两个整数 n.m. T=500000,n≤1000000,m≤1000000 Output 输出 T 行,每行一个

数学(错排):BZOJ 4517: [Sdoi2016]排列计数

4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 693  Solved: 434[Submit][Status][Discuss] Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7 取模. Input 第

bzoj-4517 4517: [Sdoi2016]排列计数(组合数学)

题目链接: 4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 846  Solved: 530[Submit][Status][Discuss] Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7 取模. I

[SDOI2016] 排列计数 (组合数学)

[SDOI2016]排列计数 题目描述 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7109+7 取模. 输入输出格式 输入格式: 第一行一个数 T,表示有 T 组数据. 接下来 T 行,每行两个整数 n.m. 输出格式: 输出 T 行,每行一个数,表示求出的序列数 输入输出样例 输入样例#1: 5 1 0 1 1

BZOJ 4517: [Sdoi2016]排列计数

4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 911  Solved: 566[Submit][Status][Discuss] Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7 取模. Input 第

[Sdoi2016]排列计数

问题 A: [Sdoi2016]排列计数 时间限制: 3 Sec  内存限制: 512 MB 题目描述 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7 取模. 输入 第一行一个数 T,表示有 T 组数据. 接下来 T 行,每行两个整数 n.m. T=500000,n≤1000000,m≤1000000 输出 输出

bzoj 4517: [Sdoi2016]排列计数【容斥原理+组合数学】

第一个一眼就A的容斥题! 这个显然是容斥的经典问题------错排,首先考虑没有固定的情况,设\( D_n \)为\( n \)个数字的错排方案数. \[ D_n=n!-\sum_{t=1}^{n}(-1)^{t-1}\sum_{i_1<i_2<...<i_t}(n-t)! \] \[ D_n=n!+\sum_{t=1}^{n}(-1)^tC_{n}^{t}(n-t)! \] \[ D_n=n!+\sum(-1)^t\frac{n!}{t!} \] 推到这一步就可以了,然后观察数据范围显

[BZOJ4517] [Sdoi2016] 排列计数 (数学)

Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7 取模. Input 第一行一个数 T,表示有 T 组数据. 接下来 T 行,每行两个整数 n.m. T=500000,n≤1000000,m≤1000000 Output 输出 T 行,每行一个数,表示求出的序列数 Sample Input 5