题目链接

BZOJ3622

题解

既已开题

那就已经没有什么好害怕的了

由题目中奇怪的条件我们可以特判掉\(n - k\)为奇数时答案为\(0\)

否则我们要求的就是糖果大于药片恰好有\(\frac{n - k}{2} + k\)个的方案数,我们记为\(K\)

思路1##

直接求恰好不好求,想到二项式反演:

如果有

\[b_k = \sum\limits_{i = k}^{n} {i \choose k} a_i
\]

那么有

\[a_k = \sum\limits_{i = k}^{n} (-1)^{i - k} {i \choose k} b_i
\]

如果我们令\(a_k\)为恰好有\(K\)对糖果大于药片的方案数

从式子来看,对于每一种\(a_i\)的情况,\(b_k\)都从中选出任意\(k\)个

那么\(b_k\)就是任选\(k\)个满足条件,剩余随便选的方案数

问题就转化为了求出\(b_k\),显然可以\(dp\)

我们先将糖果与药片分别升序排序

我们设\(f[i][j]\)表示前\(i\)个糖果选出\(j\)个和药片匹配,都大于药片的方案数

我们记\(pos_i\)为第\(i\)个糖果比药片大的最大的位置,那么如果第\(i\)个糖果参与匹配,就有\(pos_i\)种选择

由于糖果是升序排序,所以剩余\(j - 1\)个糖果选择范围一定不比\(i\)大,所以\(i\)实际剩余\(pos_i - (j - 1)\)种选择

那么有

\[f[i][j] = f[i - 1][j] + f[i - 1][j - 1] * (pos_i - j + 1)
\]

求出\(f[n][i]\),则\(b_k = f[n][k] * (n - k)!\)

然后再用二项式反演即可求出\(a_k\)

思路2##

如果你不知道二项式反演,其实有一个更直观的方法

同样是求出\(f[n][i]\)后求出\(b_i\)

我们令\(ans[k]\)表示恰好\(k\)个糖果大于药片的方案数

显然

\[ans[n] = b_n
\]

当\(k < n\)时,\(b_k\)多算了恰好为\(k + 1\)、\(k + 2\)、\(k + 3......\)的方案数,减去即可

\[ans[k] = b_k - \sum\limits_{i = k + 1}^{n} ans[i]
\]

这样也是对的

PS##

由思路2其实我们可以看到二项式反演实际上就是一个容斥的结果

思路一

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<cmath>
  6. #include<map>
  7. #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
  8. #define REP(i,n) for (int i = 1; i <= (n); i++)
  9. #define mp(a,b) make_pair<int,int>(a,b)
  10. #define cls(s) memset(s,0,sizeof(s))
  11. #define cp pair<int,int>
  12. #define LL long long int
  13. using namespace std;
  14. const int maxn = 2005,maxm = 100005,INF = 1000000000,P = 1000000009;
  15. inline int read(){
  16. int out = 0,flag = 1; char c = getchar();
  17. while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
  18. while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
  19. return out * flag;
  20. }
  21. LL f[maxn][maxn],C[maxn][maxn],fac[maxn];
  22. int a[maxn],b[maxn];
  23. int n,K;
  24. void init(){
  25. fac[0] = 1;
  26. for (int i = 1; i <= n; i++) fac[i] = fac[i - 1] * i % P;
  27. for (int i = 0; i <= n; i++){
  28. C[i][0] = C[i][i] = 1;
  29. for (int j = 1; j <= (i >> 1); j++)
  30. C[i][j] = C[i][i - j] = (C[i - 1][j - 1] + C[i - 1][j]) % P;
  31. }
  32. sort(a + 1,a + 1 + n);
  33. sort(b + 1,b + 1 + n);
  34. }
  35. int main(){
  36. n = read(); K = read();
  37. if ((n - K) & 1) {puts("0"); return 0;}
  38. K = ((n - K) >> 1) + K;
  39. for (int i = 1; i <= n; i++) a[i] = read();
  40. for (int i = 1; i <= n; i++) b[i] = read();
  41. init();
  42. f[0][0] = 1;
  43. for (int i = 1; i <= n; i++){
  44. f[i][0] = f[i - 1][0];
  45. int pos = n;
  46. while (pos && b[pos] >= a[i]) pos--;
  47. for (int j = 1; j <= i; j++)
  48. f[i][j] = (f[i - 1][j] + f[i - 1][j - 1] * max(pos - j + 1,0) % P) % P;
  49. }
  50. LL ans = 0,t;
  51. for (int i = K; i <= n; i++){
  52. t = ((i - K) & 1) ? -1 : 1;
  53. ans = ((ans + t * C[i][K] % P * (f[n][i] * fac[n - i] % P) % P) % P + P) % P;
  54. }
  55. printf("%lld\n",ans);
  56. return 0;
  57. }

思路2

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<cmath>
  6. #include<map>
  7. #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
  8. #define REP(i,n) for (int i = 1; i <= (n); i++)
  9. #define mp(a,b) make_pair<int,int>(a,b)
  10. #define cls(s) memset(s,0,sizeof(s))
  11. #define cp pair<int,int>
  12. #define LL long long int
  13. using namespace std;
  14. const int maxn = 2005,maxm = 100005,INF = 1000000000,P = 1000000009;
  15. inline int read(){
  16. int out = 0,flag = 1; char c = getchar();
  17. while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
  18. while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
  19. return out * flag;
  20. }
  21. LL f[maxn][maxn],C[maxn][maxn],fac[maxn],ans[maxn];
  22. int a[maxn],b[maxn];
  23. int n,K;
  24. void init(){
  25. fac[0] = 1;
  26. for (int i = 1; i <= n; i++) fac[i] = fac[i - 1] * i % P;
  27. for (int i = 0; i <= n; i++){
  28. C[i][0] = C[i][i] = 1;
  29. for (int j = 1; j <= (i >> 1); j++)
  30. C[i][j] = C[i][i - j] = (C[i - 1][j - 1] + C[i - 1][j]) % P;
  31. }
  32. sort(a + 1,a + 1 + n);
  33. sort(b + 1,b + 1 + n);
  34. }
  35. int main(){
  36. n = read(); K = read();
  37. if ((n - K) & 1) {puts("0"); return 0;}
  38. K = ((n - K) >> 1) + K;
  39. for (int i = 1; i <= n; i++) a[i] = read();
  40. for (int i = 1; i <= n; i++) b[i] = read();
  41. init();
  42. f[0][0] = 1;
  43. for (int i = 1; i <= n; i++){
  44. f[i][0] = f[i - 1][0];
  45. int pos = n;
  46. while (pos && b[pos] >= a[i]) pos--;
  47. for (int j = 1; j <= i; j++)
  48. f[i][j] = (f[i - 1][j] + f[i - 1][j - 1] * max(pos - j + 1,0) % P) % P;
  49. }
  50. ans[n] = f[n][n];
  51. for (int i = n - 1; i >= K; i--){
  52. ans[i] = f[n][i] * fac[n - i] % P;
  53. for (int j = i + 1; j <= n; j++)
  54. ans[i] = (ans[i] - C[j][i] * ans[j] % P) % P;
  55. ans[i] = (ans[i] + P) % P;
  56. }
  57. printf("%lld\n",ans[K]);
  58. return 0;
  59. }

BZOJ3622 已经没有什么好害怕的了 【dp + 二项式反演】的更多相关文章

  1. P4859 已经没有什么好害怕的了(dp+二项式反演)

    P4859 已经没有什么好害怕的了 啥是二项式反演(转) 如果你看不太懂二项式反演(比如我) 那么只需要记住:对于某两个$g(i),f(i)$ ---------------------------- ...

  2. bzoj3622已经没有什么好害怕的了 dp+组合+容斥(?)

    3622: 已经没有什么好害怕的了 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1033  Solved: 480[Submit][Status][ ...

  3. [BZOJ3622] 已经没有什么好害怕的了(dp+容斥)

    Description: ​ 有两个数组a和b,两两配对,求 \(a_i>b_i\) 的配对比 \(b_i>a_i\) 的配对多 \(k\) 个的方案数 \(k\le n\le 2000\ ...

  4. [bzoj3622]已经没有什么好害怕的了_动态规划_容斥原理

    bzoj-3622 已经没有什么好害怕的了 题目大意: 数据范围:$1\le n \le 2000$ , $0\le k\le n$. 想法: 首先,不难求出药片比糖果小的组数. 紧接着,我开始的想法 ...

  5. bzoj3622已经没有什么好害怕的了

    bzoj3622已经没有什么好害怕的了 题意: 给n个数Ai,n个数Bi,将Ai中的数与Bi中的数配对,求配对Ai比Bi大的比Bi比Ai大的恰好有k组的方案数.n,k≤2000 题解: 蒟蒻太弱了只能 ...

  6. BZOJ 3622 : 已经没有什么好害怕的了(dp + 广义容斥原理)

    今天没听懂 h10 的讲课 但已经没有什么好害怕的了 题意 给你两个序列 \(a,b\) 每个序列共 \(n\) 个数 , 数之间两两不同 问 \(a\) 与 \(b\) 之间有多少配对方案 使得 \ ...

  7. luoguP4859 已经没有什么好害怕的了(二项式反演)

    luoguP4859 已经没有什么好害怕的了(二项式反演) 祭奠天国的bzoj. luogu 题解时间 先特判 $ n - k $ 为奇数无解. 为了方便下记 $ m = ( n + k ) / 2 ...

  8. [BZOJ3622]已经没有什么好害怕的了(容斥DP)

    给定两个数组a[n]与b[n](数全不相等),两两配对,求“a比b大”的数对比“b比a大”的数对个数多k的配对方案数. 据说做了这题就没什么题好害怕的了,但感觉实际上这是一个套路题,只是很难想到. 首 ...

  9. BZOJ3622 已经没有什么好害怕的了 动态规划 容斥原理 组合数学

    原文链接https://www.cnblogs.com/zhouzhendong/p/9276479.html 题目传送门 - BZOJ3622 题意 给定两个序列 $a,b$ ,各包含 $n$ 个数 ...

随机推荐

  1. 如何快速查看mysql数据文件存放路径?

    进入mysql终端 mysql>show variables like '%datadir%'; 出来的结果即是!

  2. LVS基于DR模式搭建负载均衡群集

    LVS -DR模式集群架构原理图

  3. ethereum(以太坊)(七)--枚举/映射/构造函数/修改器

    pragma solidity ^0.4.10; //枚举类型 contract enumTest{ enum ActionChoices{Left,Right,Straight,Still} // ...

  4. PHP CI框架学习

    CI框架的URL辅助函数使用 URL 辅助函数文件包含一些在处理 URL 中很有用的函数 加载辅助函数 在使用CI框架的使用经常碰到跳转和路径方面的问题,site_url()和base_url()很容 ...

  5. yii2 的登录注册 轮子

    //利用到了yii2 框架之中的验证规则 进行判定而已 也不是很高深的东西  但是 使用框架自身的轮子 会有安全性能的隐患 1注册reg controller 中 我都以admin 为例子 publi ...

  6. 初见spark-03(高级算子)

    最近心情不是很好,但是需要调节自己,真的需要调节自己,还是要努力,这个世界有我喜欢的人,有我追求的人,也许真的是守的住寂寞,耐得住繁华吧. 不说别的了,今天我们来接受啊spark的高级算子的系列 1. ...

  7. Struts2---配置文件讲解及简单登录示例

    bean 用于创建一个JavaBean实例 constant 用于Struts2默认行为标签 <!-- 配置web默认编码集,相当于HttpServletRequest.setChartacte ...

  8. 5 Post实现django表单

    本节大纲 1.article-detail 评论页面的准备工作 (1)model层创建评论模型 class Comment(models.Model): """创建评论模 ...

  9. Error:Java home supplied via 'org.gradle.java.home' is invalid

    Finally i found my solution. In the project root i found gradle.properties configure this java home ...

  10. shell编程——参数传递

    1.Linux Shell参数引用 $0 这个程式的执行名字$n 这个程式的第n个参数值,n=1..9$* 这个程式的所有参数$# 这个程式的参数个数$$ 这个程式的PID$! 执行上一个背景指令的P ...