TopCoder SRM 717 Div2 C.DerangementsDiv2[数论][容斥原理][错排]

题意:从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 };
posted @ 2017-07-02 14:20  Meternal  阅读(285)  评论(0编辑  收藏  举报