题目描述

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

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

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

满足条件的序列可能很多,序列数对 109+7 取模。

输入输出格式

输入格式:

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

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

输出格式:

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

输入输出样例

输入样例#1:

  1. 5
  2. 1 0
  3. 1 1
  4. 5 2
  5. 100 50
  6. 10000 5000
输出样例#1:

  1. 0
  2. 1
  3. 20
  4. 578028887
  5. 60695423

说明

测试点 1 ~ 3: T=1000,n≤8,m≤8;

测试点 4 ~ 6: T=1000,n≤12,m≤12;

测试点 7 ~ 9: T=1000,n≤100,m≤100;

测试点 10 ~ 12:T=1000,n≤1000,m≤1000;

测试点 13 ~ 14:T=500000,n≤1000,m≤1000;

测试点 15 ~ 20:T=500000,n≤1000000,m≤1000000。

Solution:

  本题组合数学+错排公式+线推逆元。

  组合数学和逆元就不说了,介绍下错位排列。

  错位排列,顾名思义就是一个n元排列,每个元素不能排在自己的位置上的方案数,一般记作$D(n)$。

  通项公式:

    $$D_n=n!\times(1-\frac{1}{1!}+\frac{1}{2!}-\frac{1}{3!}…\frac{(-1)^n}{n!})$$

   证明:

   设$S$是由$1,2,…n$构成的所有全排列组成的集合,则$|S|=n!$。

   设$A_i$是在$1,2,…n$的所有排列种由第$i$个位置上的元素恰好是$i$的所有排列组成的集合,则有:$|A_i|=(n-1)!$。

   同理可得:$|A_i\cap A_j|=(n-2)!$

   ……

   一般情况下有:$|A_{i1}\cap A_{i2}\cap …\cap A_{ik}|=(n-k)!$。

   因为$D_n$是$S$中不满足性质$P_1,P_2,…,P_n$的元素个数,所以由容斥原理的:

   $D_n=|\overline A_1\cap \overline A_2 …\cap \overline A_n|$

     $=n!-C(n,1)*(n-1)!+C(n,2)*(n-2)!-…(-1)^nC(n,n)*0!$

     $=n!\times(1-\frac{1}{1!}+\frac{1}{2!}-…\frac{(-1)^n}{n!})$

  递推公式:

    $$D_n=(n-1)\times(D_{n-1}+D_{n-2})$$

   证明:

   第一步,把第$n$个元素放在一个位置,比如位置$k$,一共有$n-1$种方法;

   第二步,放编号为$k$的元素,这时有两种情况:(1)把它固定到位置$n$,由于第$n$个元素固定到了位置$k$,剩下$n-2$个元素就有$D_{n-2}$种方法;(2)第$k$个元素不能放到位置$n$,而第$n$个元素固定到了位置$k$,于是$n-1$个元素,有$D_{n-1}$种方法;

   综上得到$D_n = (n-1) \times(D_{n-2} + D_{n-1})$,特殊地,$D_1=0, D_2=1$。

  当然更为常用的是后面的递推公式,比如本题。

  不难发现本题答案为$C(n,m)\times D(n-m)$。

  于是我们只要预处理出$10^6$内的阶乘取模、阶乘的逆元、错排的方案数就好了。

代码:

  1. /*Code by 520 -- 9.14*/
  2. #include<bits/stdc++.h>
  3. #define il inline
  4. #define ll long long
  5. #define RE register
  6. #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
  7. #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
  8. using namespace std;
  9. const ll N=,mod=1e9+;
  10. int n,m;
  11. ll d[N],c[N],inv[N];
  12.  
  13. int gi(){
  14. int a=;char x=getchar();
  15. while(x<''||x>'')x=getchar();
  16. while(x>=''&&x<='')a=(a<<)+(a<<)+(x^),x=getchar();
  17. return a;
  18. }
  19.  
  20. il void Pre(){
  21. d[]=,d[]=;
  22. For(i,,) d[i]=(i-)*(d[i-]+d[i-])%mod;
  23. c[]=,c[]=,inv[]=;
  24. For(i,,) c[i]=c[i-]*i%mod,inv[i]=(mod-mod/i*inv[mod%i]%mod)%mod;
  25. For(i,,) inv[i]=inv[i]*inv[i-]%mod;
  26. }
  27.  
  28. int main(){
  29. Pre();
  30. int T=gi();
  31. while(T--) {
  32. n=gi(),m=gi();
  33. if(n-m==) printf("0\n");
  34. else if(n==m) printf("1\n");
  35. else if(!m) printf("%lld\n",d[n]);
  36. else printf("%lld\n",c[n]*inv[m]%mod*inv[n-m]%mod*d[n-m]%mod);
  37. }
  38. return ;
  39. }

P4071 [SDOI2016]排列计数的更多相关文章

  1. 洛谷——P4071 [SDOI2016]排列计数(错排+组合数学)

    P4071 [SDOI2016]排列计数 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列 ...

  2. 洛谷 P4071 [SDOI2016]排列计数 题解

    P4071 [SDOI2016]排列计数 题目描述 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳 ...

  3. 洛谷P4071 [SDOI2016] 排列计数 [组合数学]

    题目传送门 排列计数 题目描述 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m ...

  4. Luogu P4071 [SDOI2016]排列计数

    晚上XZTdalao给我推荐了这道数论题.太棒了又可以A一道省选题了 其实这道题也就考一个错排公式+组合数+乘法逆元 我们来一步一步分析 错排公式 通俗的说就是把n个1~n的数排成一个序列A,并使得所 ...

  5. 洛谷 P4071 [SDOI2016]排列计数

    洛谷 这是一道组合数学题. 对于一个长为n的序列,首先我们要选m个使之稳定\(C^{m}_{n}\). 且要保证剩下的序列不稳定,即错排\(D_{n-m}\). 所以答案就是:\[ANS=C^{m}_ ...

  6. P4071 [SDOI2016]排列计数 题解

    分析: 线性求逆元:https://blog.csdn.net/qq_34564984/article/details/52292502 代码: #include<cstdio> usin ...

  7. 数学【洛谷P4071】 [SDOI2016]排列计数

    P4071 [SDOI2016]排列计数 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列 ...

  8. BZOJ 4517: [Sdoi2016]排列计数

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 911  Solved: 566[Submit][Status ...

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

    题目链接: 4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 846  Solved: 530[Submit][ ...

随机推荐

  1. AutomaticInteger中CAS运用分析

    摘要 在接触CAS的时候虽然对它流程了解了但是对其如何解决并发问题还是一直有疑问的,所以在就选择了java中典型线程安全的AtomicInteger类进行了源码的分析. CAS简介 CAS的全称为co ...

  2. hdfs命令大全

    hdfs常用命令: 第一部分:hdfs文件系统命令 第一类:文件路径增删改查系列: hdfs dfs -mkdir dir  创建文件夹 hdfs dfs -rmr dir  删除文件夹dir hdf ...

  3. docker node项目 连接mongodb

    在弄docker部署node项目的时候遇到了连接mongdb的问题,记录一下问题解决办法 一.Docker 安装 MongoDB 1.查找Docker Hub上的mongo镜像 [root@VM_49 ...

  4. spring 在ssh三大框架中充当的角色

    https://blog.csdn.net/yeah_nn/article/details/79992777

  5. Docker持久化存储与数据共享

    一.Docker持久化数据的方案 基于本地文件系统的Volume:可以在执行docker create或docker run时,通过-v参数将主机的目录作为容器的数据卷.这部分功能便是基于本地文件系统 ...

  6. EOS博彩合约设计

    集中博彩游戏合约设计 一.功能接口 1. 质押deposit 由用户发起,用户将个人账户中token质押给平台,从而可以进入平台去参与平台活动. 2. 赎回withdraw 由用户发起,在用户结束平台 ...

  7. 冲刺One之站立会议6 /2015-5-19

    2015-5-19 今天把服务器端的界面完善了一下,然后大家查了好多资料,实现了登陆界面实际连接的功能,开始加了一个它和服务器的的跳转,但是分析过后发现这是个没有必要的跳转.登录应该直接转到聊天室的主 ...

  8. 使用exe4j将jar包导出为exe

    Exe4J使用方法 此工具是将Java程序包装成exe格式文件工具.(点击exe4j\bin\exe4j.exe文件)启动后如下图所示 如果未注册,则可使用这个注册码:A-XVK209982F-1y0 ...

  9. 第二次作业利用java语言编写计算器进行四则运算

    随着第一次作业的完成,助教 牛老师又布置了第二次作业:用java语言编写一个程序然后进行四则运算用户用键盘输入一个字符来结束程序显示统计结果.一开始看到这个题目我也着实吓了一跳 因为不知道如何下手而且 ...

  10. 灵悟礼品网上专卖店——画出E-R图

    一.小组成员: 洪雪意(产品负责人) 陈淑筠(Master) 二.组内人员任务情况 计划完成的任务的第三个模块:分析并建立数据库 已完成的任务: 任务的第三个模块: 陈淑筠(完成任务1):画出商品资料 ...