D、Homework of PE 容斥原理
终于想懂了这个容斥,
华工4月23号校赛,
考虑总的所有情况,设1---n里面含有质数的个数为all,需要固定m个质数。那么有
totSum = C(all, m) * (n - m)!,就是在all个质数里面,任意选m个出来固定,剩下的全排。
但是算多了,因为还有一些质数(不在那m个之内)也会被固定,
而且,考虑样例
5 1,
1 2 3 4 5
这个时候,先考虑任选m个出来固定,题目就是任选1个出来固定。剩下的全排
比如固定了2,剩下的全排,会产生,只固定了2,固定了2、3,固定了2、5,固定了2、3、5
比如固定了3,剩下的全排,会产生,只固定了3,固定了2、3,固定了3、5,固定了2、3、5
比如固定了5,剩下的全排,会产生,只固定了5,固定了2、5,固定了3、5,固定了2、3、5
那么只有第一列相加的才是正确答案。后面的要减去。
减去固定了两个的时候,
这个时候前面一个已经固定了,再枚举一个来固定,就是固定2个。所以固定(3, 2)和(2, 3)是不同的方案。
固定了(2, 3)时,会有,只固定2、3和固定了2、3、5
固定了(3, 2)时,会有,只固定3、2和固定了3、2、5
.....
等等。
减去这些后,会发现结果是ans - 3 * (固定了2、3、5),加回来就是了。
就是一个容斥,以后容斥要实打实写出来,毕竟不是大神。
哭~~~~
比赛没想到。刚才也想了很久,光想是不行的。要模拟。
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> #include <bitset> bool check(int val) { int en = (int)sqrt(val); for (int i = 2; i <= en; ++i) { if (val % i == 0) return false; } return true; } const int MOD = 1e9 + 7; LL fac[222]; LL quick_pow(LL a, LL b, LL MOD) { LL base = a % MOD; LL ans = 1; while (b) { if (b & 1) { ans = ans * base % MOD; } base = base * base % MOD; b >>= 1; } return ans; } LL C(LL n, LL m, LL MOD) { if (n < m) return 0; if (n == m) return 1 % MOD; LL ans1 = 1; LL ans2 = 1; LL mx = max(n - m, m); LL mi = n - mx; for (int i = 1; i <= mi; ++i) { ans1 = ans1 * (mx + i) %MOD; ans2 = ans2 * i % MOD; } return (ans1 * quick_pow(ans2, MOD - 2, MOD) % MOD); } int n, m; void work() { fac[0] = 1; for (int i = 1; i <= 200; ++i) { fac[i] = fac[i - 1] * i % MOD; } int all = 0; for (int i = 2; i <= n; ++i) { all += check(i); } LL ans = C(all, m, MOD) * fac[n - m] % MOD; // cout << ans << endl; for (int i = 1; i <= all - m; ++i) { if (i & 1) { ans = (ans + MOD - C(all, m, MOD) * C(all - m, i, MOD) % MOD * fac[n - (m + i)] % MOD) % MOD; } else ans = (ans + C(all, m, MOD) * C(all - m, i, MOD) % MOD * fac[n - (m + i)] % MOD) % MOD; } cout << ans % MOD << endl; } int main() { #ifdef local freopen("data.txt", "r", stdin); #endif scanf("%d%d", &n, &m); work(); return 0; }
posted on 2017-04-25 14:00 stupid_one 阅读(264) 评论(0) 编辑 收藏 举报