题目描述

求有多少种长度为 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

输出

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

样例输入

5
1 0
1 1
5 2
100 50
10000 5000

样例输出

0
1
20
578028887
60695423


题解

组合数+dp

题目中说n个数有m个稳定的,有n-m个不稳定的,那么我们可以从这n个数中选出m个作为稳定的数,其余的n-m个作为不稳定的数。

n选m需要用到组合数,然而n和m太大不能递推来求。

考虑到C(n,m)=n!/(m!(n-m)!),我们可以先预处理阶乘模MOD的值,再用乘法逆元。

而这里的MOD为质数,根据费马小定理,ap≡a(mod p),即ap-1≡1(mod p),即a*ap-2≡1(mod p),即1/a≡ap-2(mod p)

所以直接用快速幂求aMOD-2就是乘法逆元。

然后是n-m个不稳定的,即错排,dp公式:f[n]=(n-1)*(f[n-1]+f[n-2])

解释:第n个物品有n-1个位置可选,假设选定了k位置,考虑k的选择分两种,不选n和选n。不选n的情况,将n看作k,即k不能选择自身,转化为f[n-1];选N的情况即f[n-2]。

乘起来模上MOD即可。

#include <cstdio>
#define N 1000010
#define MOD 1000000007
typedef long long ll;
ll fac[N] , f[N];
ll qpow(ll x , int y)
{
ll ans = 1;
while(y)
{
if(y & 1) ans = (ans * x) % MOD;
x = (x * x) % MOD , y >>= 1;
}
return ans;
}
int main()
{
int i , T , n , m;
fac[0] = 1;
for(i = 1 ; i <= 1000000 ; i ++ ) fac[i] = fac[i - 1] * i % MOD;
f[0] = 1 , f[1] = 0;
for(i = 2 ; i <= 1000000 ; i ++ ) f[i] = (i - 1) * (f[i - 1] + f[i - 2]) % MOD;
scanf("%d" , &T);
while(T -- )
{
scanf("%d%d" , &n , &m);
printf("%lld\n" , qpow(fac[m] , MOD - 2) * qpow(fac[n - m] , MOD - 2) % MOD * fac[n] % MOD * f[n - m] % MOD);
}
return 0;
}

【bzoj4517】[Sdoi2016]排列计数 组合数+dp的更多相关文章

  1. BZOJ4517 Sdoi2016 排列计数 【DP+组合计数】*

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

  2. bzoj4517[Sdoi2016]排列计数(组合数,错排)

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 1792  Solved: 1111[Submit][Stat ...

  3. BZOJ4517: [Sdoi2016]排列计数(组合数+错位排列)

    Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 1626  Solved: 994[Submit][Status][Discuss] Descripti ...

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

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

  5. [BZOJ4517][SDOI2016]排列计数(错位排列)

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 1616  Solved: 985[Submit][Statu ...

  6. BZOJ4517 [Sdoi2016]排列计数 【组合数 + dp】

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

  7. 洛谷P2606 [ZJOI2010]排列计数(组合数 dp)

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

  8. bzoj4517: [Sdoi2016]排列计数--数学+拓展欧几里得

    这道题是数学题,由题目可知,m个稳定数的取法是Cnm 然后剩下n-m本书,由于编号为i的书不能放在i位置,因此其方法数应由错排公式决定,即D(n-m) 错排公式:D[i]=(i-1)*(D[i-1]+ ...

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

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

随机推荐

  1. motto - MySQL - 常用命令

    本文搜索关键字:motto mysql 登录数据库 mysql -uroot -proot -P3306 -h127.0.0.1 --prompt "\u@\h \d>" - ...

  2. LintCode 12.带最小值操作的栈(两种方法实现)

    题目描述 实现一个带有取最小值min方法的栈,min方法将返回当前栈中的最小值. 你实现的栈将支持push,pop 和 min 操作,所有操作要求都在O(1)时间内完成. 样例 如下操作:push(1 ...

  3. 浅谈Linux下mv和cp命令的区别

    1.功能上的区别 mv:用户可以使用该命令为文件或目录重命名或将文件由一个目录移入另一个目录中. cp: 该命令的功能是将给出的文件或目录拷贝到另一文件或目录中. 2.从inode角度来区分 mv:会 ...

  4. 富文本编辑器 wangEditor.js

    1.引用 wangEditor 相关js  和 css 下载地址:https://files.cnblogs.com/files/kitty-blog/WangEditor.zip 3.页面: < ...

  5. 使用jQuery实现数字逆时针旋转

    要实现数字逆转,最主要是分析我们页面的元素结果,结合选择器充分利用起来! 例如:以下lable中每一个id和值的安排具有一定结构的意义需要用心分析: jQuery代码:

  6. ts包、表、子表、section的关系

    我们经常接触到创建 DEMUX,注册 Filter 过滤数据, 通过回调过滤出 section 数据,然后我们对 section 数据做具体的解析或者其他操作. 我们这里说的 section 就是段的 ...

  7. C中 snprintf()函数的作用

    函数原型:int snprintf(char* dest_str,size_t size,const char* format,...); 函数功能:先将可变参数 “…” 按照format的格式格式化 ...

  8. 函数:引用file类对象及io类对象作为参数打印文本及显示文本

    #include <iostream> #include <fstream> #include <cstdlib> using namespace std; voi ...

  9. C++ 求阶乘

    #include<iostream> using namespace std; ; //输入阶乘数 int main() { long long factorial[size]; fact ...

  10. SpringCloud项目,接口调用返回http 500 - Internal Server Error的错误

    今天上班的时候,自己正在参与的Spring Cloud项目出现了问题,原本上周五还正常的项目突然所有接口调用都是返回http 500的错误. 项目的状态是在Eureka上可以看到对应微服务是在线状态, ...