zoukankan      html  css  js  c++  java
  • bzoj3622 已经没有什么好害怕的了

    题目描述:

    bz

    luogu

    题解:

    $dp$+二项式反演。

    首先把两个集合排序,然后dp。$dp[i][j]$表示前$i$个糖果里面我让$j$个匹配比它小的药片,剩下不管的方案数。

    容易得到方程为$dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+(lim-(j-1))$,其中$lim$表示比它小的药片的数量。

    这一部分是$O(n^2)$的。

    发现他问的是$cnt(a>b)-cnt(a<b)==k$,那么$cnt(a>b)=(n+k)/2$。

    dp之后我们得到了对于$n$个糖果,我们让其中$i$个匹配,剩下$n-i$个瞎匹配的方案数。

    这个时候用二项式反演容斥就好了。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MOD = 1000000009;
    const int N = 2050;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    int fastpow(int x,int y)
    {
        int ret = 1;
        while(y)
        {
            if(y&1)ret=1ll*ret*x%MOD;
            x=1ll*x*x%MOD;y>>=1;
        }
        return ret;
    }
    int n,k,a[N],b[N],dp[N][N],f[N],jc[N],jny[N];
    void Mod(int&x){if(x>=MOD)x-=MOD;}
    void init()
    {
        jc[0] = 1;for(int i=1;i<=n;i++)jc[i]=1ll*jc[i-1]*i%MOD;
        jny[n]=fastpow(jc[n],MOD-2);for(int i=n;i>=1;i--)jny[i-1]=1ll*jny[i]*i%MOD;
    }
    int C(int x,int y){return 1ll*jc[x]*jny[y]%MOD*jny[x-y]%MOD;}
    int main()
    {
    //    freopen("tt.in","r",stdin);
        read(n),read(k);
        if((n^k)&1){puts("0");return 0;}
        k = (n+k)>>1;init();
        for(int i=1;i<=n;i++)
            read(a[i]);
        for(int i=1;i<=n;i++)
            read(b[i]);
        sort(a+1,a+1+n),sort(b+1,b+1+n);
        dp[0][0]=1;
        for(int i=1,j=0;i<=n;i++)
        {
            while(j+1<=n&&a[i]>b[j+1])j++;
            for(int k=0;k<=j;k++)
            {
                dp[i][k]=dp[i-1][k];
                if(k)Mod(dp[i][k]+=1ll*dp[i-1][k-1]*(j-k+1)%MOD);
            }
        }
        for(int i=1;i<=n;i++)
            f[i] = 1ll*dp[n][i]*jc[n-i]%MOD;
        int ans = 0;
        for(int i=k;i<=n;i++)
        {
            if((i-k)&1)Mod(ans+=MOD-1ll*f[i]*C(i,k)%MOD);
            else Mod(ans+=1ll*f[i]*C(i,k)%MOD);
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    浴谷夏令营2017.8.1数论的整理
    BZOJ1483: [HNOI2009]梦幻布丁
    NOIP2014-11-3模拟赛
    BZOJ3884: 上帝与集合的正确用法
    BZOJ4869: [Shoi2017]相逢是问候
    计蒜客NOIP2017提高组模拟赛(三)day1
    NOIP2014-9-6模拟赛
    NOIP2014-7-7模拟赛
    zoj Little Keng(快速幂)
    多校Key Set (快速幂)
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/11059661.html
Copyright © 2011-2022 走看看