zoukankan      html  css  js  c++  java
  • 【BZOJ3622】已经没什么好害怕的了 容斥原理+dp

    Description

    img

    Input

    img

    Output

    img

    Sample Input

    4 2
    5 35 15 45
    40 20 10 30

    Sample Output

    4

    HINT

    img

    输入的2*n个数字保证全不相同。

    还有输入应该是第二行是糖果,第三行是药片

    Sol

    先把两个数组排序,能够把题目的分析难度降低一些。

    然后我们求出(r[i])表示b中小于(a[i])的最靠右的位置,这样dp的时候就能够(O(1))转移了。

    (f[i][j])表示考虑了i位,至少有j个满足a>b的方案数。

    显然(f[i][j]=f[i-1][j]+f[i-1][j-1]*max(0,r[i]-j+1))

    这样的方案数是“至少”,我们需要求的是“恰好”,所以需要容斥一波。

    (g[i])表示恰好i个的方案数,那么我们的计算方法就是用全部情况减去不合法的情况。

    显然全部情况是(f[n][i]*(n-i)!),阶乘就表示剩下的可以任意选择。

    然后我们需要减去的是:(sum_{j=i+1}^{n}g[j]*C(j,i))

    这个式子的意义是:对于每个恰好是j的方案的排列中,任意选择i个数字的方案数,也就是不合法的总方案数。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,a[2005],b[2005],f[2005][2005],g[2005],d[2005]={1},c[2005][2005],r[2005],P=1e9+9;
    int main()
    {
    	scanf("%d%d",&n,&m);m=(m+n)>>1;
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);sort(a+1,a+n+1);
    	for(int i=1;i<=n;i++) scanf("%d",&b[i]);sort(b+1,b+n+1);
    	for(int i=1,j=1;i<=n;r[i]=j-1,i++) for(;j<=n&&b[j]<a[i];j++);
    	for(int i=0,j;i<=2000;i++) for(c[i][0]=1,j=1;j<=i;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%P;
    	for(int i=1;i<=2000;i++) d[i]=1ll*d[i-1]*i%P;
    	for(int i=0;i<=n;i++) f[i][0]=1;
    	for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) f[i][j]=(f[i-1][j]+1ll*f[i-1][j-1]*max(r[i]-j+1,0)%P)%P;
    	for(int i=n,j;i>=m;i--) for(g[i]=1ll*f[n][i]*d[n-i]%P,j=i+1;j<=n;j++) g[i]=(g[i]-1ll*c[j][i]*g[j]%P+P)%P;
    	printf("%d
    ",g[m]);
    }
    
  • 相关阅读:
    jar
    8月21日23:38
    WPF之UI虚拟化
    (转)Windows系统白名单以及UAC机制
    C#获取文件版本信息
    命名实体识别,使用pyltp提取文本中的地址
    (转载)完成端口(Completion Port, I/OCP)详解
    全国各城市地名抓取,包含街道、村落、小区、商店、景点等
    关于Python打包运行的一些思路
    关于批判性思维(Critical Thinking)
  • 原文地址:https://www.cnblogs.com/CK6100LGEV2/p/9414949.html
Copyright © 2011-2022 走看看