[BZOJ4517][SDOI2016]排列计数(排列组合)
2017-10-28 19:52
375 查看
先考虑怎样求出1到n的所有排列中,错排(一个1到n的排列A[1],A[2],...,A[n]的每一个值都有i≠A[i])的个数Dn。
先考虑Dn的容斥求法:Dn=Ann−An−1n+An−2n−An−3n+...+(−1)nA0n。
把A化为阶乘形式后,利用分配律可以得到D的递推式:
1、D0=1
2、当i是奇数时,Dn=Dn−1∗n−1
3、当i是偶数时,Dn=Dn−1∗n+1
回到原问题。可以发现,如果固定了满足i=A[i]的m个位置,那么剩下的n−m个数必将组成一个n−m个数的错排。
所以答案=Cmn∗Dn−m。预处理阶乘,阶乘逆元和D之后就可以O(1)求解一组数据了。
代码:
先考虑Dn的容斥求法:Dn=Ann−An−1n+An−2n−An−3n+...+(−1)nA0n。
把A化为阶乘形式后,利用分配律可以得到D的递推式:
1、D0=1
2、当i是奇数时,Dn=Dn−1∗n−1
3、当i是偶数时,Dn=Dn−1∗n+1
回到原问题。可以发现,如果固定了满足i=A[i]的m个位置,那么剩下的n−m个数必将组成一个n−m个数的错排。
所以答案=Cmn∗Dn−m。预处理阶乘,阶乘逆元和D之后就可以O(1)求解一组数据了。
代码:
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res; } const int MaxN = 1e6, N = MaxN + 5, PYZ = 1e9 + 7; int n, m, A , D , inv ; int qpow(int a, int b) { int res = 1; while (b) { if (b & 1) res = 1ll * res * a % PYZ; a = 1ll * a * a % PYZ; b >>= 1; } return res; } int C(int n, int m) { return 1ll * A * inv[m] % PYZ * inv[n - m] % PYZ; } void init() { int i; A[0] = D[0] = 1; for (i = 1; i <= MaxN; i++) { A[i] = 1ll * A[i - 1] * i % PYZ; D[i] = (1ll * D[i - 1] * i + (i & 1 ? -1 : 1)) % PYZ; if (D[i] < 0) D[i] += PYZ; } inv[MaxN] = qpow(A[MaxN], PYZ - 2); for (i = MaxN - 1; i >= 0; i--) inv[i] = 1ll * inv[i + 1] * (i + 1) % PYZ; } void work() { n = read(); m = read(); printf("%d\n", 1ll * C(n, m) * D[n - m] % PYZ); } int main() { init(); int T = read(); while (T--) work(); return 0; }
相关文章推荐
- BZOJ4517 & 洛谷4071:[SDOI2016]排列计数——题解
- [bzoj4517][Sdoi2016]排列计数 组合数+逆元
- Bzoj 4517: [Sdoi2016]排列计数(排列组合)
- 【BZOJ4517】【Sdoi2016】排列计数 线性逆元 错位排列
- BZOJ4517: [Sdoi2016]排列计数
- bzoj4517: [Sdoi2016]排列计数
- [BZOJ4517][SDOI2016]排列计数(错位排列)
- BZOJ4517 [Sdoi2016]排列计数
- BZOJ4517 [Sdoi2016]排列计数 【组合数 + dp】
- [bzoj4517][SDOI2016]排列计数
- bzoj4517: [Sdoi2016]排列计数
- 【bzoj4517】【SDOI2016】排列计数
- bzoj4517 [Sdoi2016]排列计数 (错排 + 组合数)
- BZOJ4517: [Sdoi2016]排列计数
- [bzoj4517][Sdoi2016]排列计数
- bzoj4517 [Sdoi2016]排列计数
- Bzoj4517 [Sdoi2016]排列计数
- bzoj4517: [Sdoi2016]排列计数
- 【bzoj4517】 Sdoi2016—排列计数
- bzoj4517 [Sdoi2016]排列计数