P4071 [SDOI2016]排列计数

题目描述

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

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

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

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

输入格式

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

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

输出格式

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

输入输出样例

输入 #1

5

1 0

1 1

5 2

100 50

10000 5000

输出 #1

0

1

20

578028887

60695423

说明/提示

测试点 1 ~ 3: $ T = 1000\(,\)n \leq 8\(,\)m \leq 8$;

测试点 4 ~ 6: $ T = 1000\(,\)n \leq 12\(,\)m \leq 12$;

测试点 7 ~ 9: $ T = 1000\(,\)n \leq 100\(,\)m \leq 100$;

测试点 10 ~ 12:$ T = 1000\(,\)n \leq 1000\(,\)m \leq 1000$;

测试点 13 ~ 14:$ T = 500000\(,\)n \leq 1000\(,\)m \leq 1000$;

测试点 15 ~ 20:$ T = 500000\(,\)n \leq 1000000\(,\)m \leq 1000000$。

【思路】

组合数学 / 错排

【题目大意】

a[i]在i的位置上面是稳定的

求有m个数是稳定的序列有多少个

【题目分析】

求符合条件序列的个数

符合条件序列可以先只看那稳定的数

一个序列中只有m个数是稳定的

其他的都是稳定的

那么稳定的数组合方式就是n个数里面取m个

因为如果稳定那一个数只对应一个位置

所以不存在顺序这一说,所以就是 \(C_n^m\)

知道了稳定数的组合方式

拿在看看除了这些稳定数之外数的组合方式

其他的数都是不在自己的位置上面的

也就是错排

直接用错排求出n-m(这里是减号下同下下同)个人错排方法的数量就好了

因为一种稳定数对应n-m个人的错排方式

所以数量数就是 \(C_n^m\) * (n-m)个人的错排方式

【存在的问题】

1.因为n和m的数据范围都是小于等于1e6

不是很小,而且T很大,

所以每次T 不能都单独求C和错排次数了

这样一定会超时

2.因为这道题中有取模运算

而递推求组合数只能过2000所以用这个阶乘求组合数就是必然的了

那么就要用到除法

而取模运算中不能用除法

【优化】

1.针对问题1

多次求解会超时

那就先预处理出来所有的阶乘和i个人的错排方式

到时候O(1)查询就好了

2.针对问题2

既然不能用除法那就用乘法

用逆元来代替除法就可以啦

求逆元因为模数是质数

所以可以用费马小定理求

费马小定理求逆元详见

这里

【完整代码】

#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int k = 1e9 + 7;
const int Max = 1000005;
int d[Max];
int f[Max];
int inv[Max]; int p(int a,int b)
{
int ans = 1;
while(b)
{
if(b & 1)
ans = ans * a % k;
b >>= 1;
a = a * a % k;
}
return ans;
} signed main()
{
d[0] = 1,d[2] = 1;
for(register int i = 3;i <= 1000000;++ i)
d[i] = (i - 1) * (d[i - 1] + d[i - 2]) % k;
f[0] = 1,f[1] = 1;
for(register int i = 2;i <= 1000000;++ i)
f[i] = f[i - 1] * i % k;
inv[0] = p(f[0],k - 2);
for(register int i = 1;i <= 1000000;++ i)
inv[i] = p(f[i],k - 2) % k;
int t;
cin >> t;
while(t --)
{
int n,m;
scanf("%lld%lld",&n,&m);
//c(n,m) * d(n-m)
//n!/m!(n - m)! * d[n-m]
printf("%lld\n",(f[n] * inv[m] % k * inv[n-m] % k * d[n-m]) % k);
}
return 0;
}

洛谷 P4071 [SDOI2016]排列计数 题解的更多相关文章

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

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

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

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

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

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

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

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

  5. 洛谷 P2606 [ZJOI2010]排列计数 解题报告

    P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...

  6. BZOJ4517 & 洛谷4071:[SDOI2016]排列计数——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4517 https://www.luogu.org/problemnew/show/P4071 求有 ...

  7. ●洛谷P2606 [ZJOI2010]排列计数

    题链: https://www.luogu.org/problemnew/show/P2606题解: 组合数(DP),Lucas定理 首先应该容易看出,这个排列其实是一个小顶堆. 然后我们可以考虑dp ...

  8. 洛谷P2606 [ZJOI2010]排列计数

    题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很 ...

  9. 洛谷P2606 [ZJOI2010]排列计数(数位dp)

    题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很 ...

随机推荐

  1. [CF30E]Tricky and Clever Password(KMP+manacher)

    首先枚举回文中心,然后显然中心两边要尽量扩展作为middle,这个用manacher实现. 然后注意到suffix的结尾位置是固定的(串尾),那么预处理出以每个位置结尾的串与原串后缀至多能匹配多长,然 ...

  2. elasticsearch内存不断增长问题

    经过一段时间运行,es的索引已经达到数十G以上.es采用mmap的方式将索引文件映射到内存中,随着检索的次数增加,越来越多的数据被操作系统读入到内存中.这部分内存位于系统中,但是又不归es管理,也就是 ...

  3. Java——简单实现学生管理系统

    import java.io.*;import java.util.ArrayList;import java.util.Scanner;class MyObjectOutputStream exte ...

  4. 2019 东软java面试笔试题 (含面试题解析)

    本人3年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.东软等公司offer,岗位是Java后端开发,最终选择去了东软. 面试了很多家公司,感觉大部分公司考察的点都差不多 ...

  5. Tornado + Bootstrap 快速搭建自己的web应用

    前言 最近用 python tordado 框架, 整了一个模板页面, 用于接入与发布数据的展示, tornado 简单易用, bootstrap 比较流行, 用起来也省事, 配合起来做些小案例非常迅 ...

  6. python基础知识(七)---数据类型补充、"雷区"、编码

    数据类型补充."雷区".编码 1.数据类型补充 str: #字符串数据类型补充 s1=str(123) #常用于类型转换 print(s1) #capitalize()首字母大写 ...

  7. FFMPEG_avi转码到mp4(aac+h264)源码

    #include <ffmpeg/avcodec.h>#include <ffmpeg/avformat.h>#include <stdio.h>#include ...

  8. 基于 K8S 集群安装部署 istio-1.2.4

    使用云平台可以为组织提供丰富的好处.然而,不可否认的是,采用云可能会给 DevOps 团队带来压力.开发人员必须使用微服务以满足应用的可移植性,同时运营商管理了极其庞大的混合和多云部署.Istio 允 ...

  9. centos7 docker安装Jenkins BlueOcean

    Jenkins是一款Java开发的跨平台持续集成和持续发布的开源项目,Jenkins已经作为各大公司进行CI/CD的首选工具.而BlueOcean是Jenkins推出的一个插件,其目的就是让程序员执行 ...

  10. Pycharm中连接数据库乱码问题解决

    当我们使用pycharm建立数据库之后,看到里面的数据都是乱码,就像下面一样: 其实这个并不是pycharm的显示问题,而是建立数据库时产生的. 解决方法是到指定字符集的命令提示符中重新建表并指定字符 ...