题意:从1到n+m的数组中选m个数字且每个数字和在原数组中下标不同,求方案数。例如 n=1 m = 2 则存在{2,1},{2,3},{3,1}
题解:错排问题模板 下面是使用容斥原理推导的过程
1. 先推导标准的错排公式 假设为从1到m的m个数字组成的数组
令k=非错排的数字个数 共有m!种情况,需要减去非错排的所有情况。例如减去k=1时则有m个情况(位置为1,2...m的数字不是错排)方案数为$C_{\text{m}}^1 \times ({\text{m - 1)!}}$,以此类推因为容斥原理添加k=2时方案数为$C_{\text{m}}^2 \times ({\text{m - 2)!}}$
则错排的方案数为${\text{m}}! - \sum\limits_{k = 1}^m {{{( - 1)}^k}C_{\text{m}}^k \times ({\text{m - k)!}}} $
2.在题目中 方程应改为 ${\text{(m + n)}}! - \sum\limits_{k = 1}^m {{{( - 1)}^k}C_{\text{m}}^k \times ({\text{n + m - k)!}}}$
(m+n)!全排列方案数 减去前m个存在的所有错排方案数。
代码:
1 #define _CRT_SECURE_NO_DEPRECATE 2 #pragma comment(linker, "/STACK:102400000,102400000") 3 #include<iostream> 4 #include<cstdio> 5 #include<fstream> 6 #include<iomanip> 7 #include<algorithm> 8 #include<cmath> 9 #include<deque> 10 #include<vector> 11 #include<bitset> 12 #include<queue> 13 #include<string> 14 #include<cstring> 15 #include<map> 16 #include<stack> 17 #include<set> 18 #include<functional> 19 #define pii pair<int, int> 20 #define mod 1000000007 21 #define mp make_pair 22 #define pi acos(-1) 23 #define eps 0.00000001 24 #define mst(a,i) memset(a,i,sizeof(a)) 25 #define all(n) n.begin(),n.end() 26 #define lson(x) ((x<<1)) 27 #define rson(x) ((x<<1)|1) 28 #define inf 0x3f3f3f3f 29 typedef long long ll; 30 typedef unsigned long long ull; 31 using namespace std; 32 33 const int maxn = 55; 34 class DerangementsDiv2 { 35 public: 36 ll c[maxn][maxn]; 37 ll fac[170]; 38 int count(int n, int m) 39 { 40 mst(c, 0); 41 mst(fac, 0); 42 fac[0] = 1; 43 for (int i = 1; i <= 150; ++i) 44 fac[i] = (fac[i - 1] * (ll)i) % mod; 45 c[0][0] = 1; 46 for (int i = 1; i <= 53; ++i) 47 { 48 c[i][0] = 1; 49 for (int j = 1; j <= i; ++j) 50 c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod; 51 } 52 ll ans = fac[n + m]; 53 ll cas = -1; 54 for (int i = 1; i <= m; ++i) 55 { 56 ans = (ans + ((cas*fac[n + m - i] * c[m][i]) % mod) + mod) % mod; 57 cas *= -1; 58 } 59 60 return ans; 61 } 62 };
时间: 2024-10-09 21:51:49